2016-08-14 4 views
2

Я пытаюсь понять, как «плавление» работает в сложных ситуациях. Я видел много сообщений и блогов об использовании этих пакетов в очень простых случаях - но не в более сложных. Например:Комплексное плавление с dplyr, tidyr, reshape2 in R

Допустим, у меня есть следующие данные в dataframe:

CA UNIT  SCP DATE1 TIME1 DESC1 ENTRIES1 EXITS1 
1 A002 R051 02-00-00 07-27-13 00:00:00 REGULAR 4209603 1443585 
2 A002 R051 02-00-00 07-28-13 08:00:00 REGULAR 4210490 1443821 
3 A002 R051 02-00-00 07-29-13 16:00:00 REGULAR 4211586 1444302 
4 A002 R051 02-00-00 07-30-13 14:01:46 LOGON 4213192 1444700 
5 A002 R051 02-00-00 07-30-13 16:00:00 REGULAR 4213333 1444737 
6 A002 R051 02-00-00 08-01-13 00:00:00 REGULAR 4215894 1445274` 

и продолжение столбцов вправо (к сожалению, я не мог отформатировать его надлежащим образом в блоке кода):

 `DATE2 TIME2  DESC2 ENTRIES2 EXITS2 
1 07-27-13 08:00:00 REGULAR 4209663 1443616 
2 07-28-13 16:00:00 REGULAR 4210775 1443921 
3 07-30-13 00:00:00 REGULAR 4212845 1444369 
4 07-30-13 14:02:18 DOOR OPEN 4213192 1444700 
5 07-31-13 00:00:00 REGULAR 4214345 1444823 
6 08-01-13 08:00:00 REGULAR 4215977 1445362` 

, и я хочу, чтобы расплавить это в dataframe в следующем формате:

CA UNIT  SCP DATE TIME  DESC ENTRIES EXITS 
1 A002 R051 02-00-00 07-27-13 00:00:00 REGULAR 4209603 1443585 
2 A002 R051 02-00-00 07-28-13 08:00:00 REGULAR 4210490 1443821 
3 A002 R051 02-00-00 07-29-13 16:00:00 REGULAR 4211586 1444302 
4 A002 R051 02-00-00 07-30-13 14:01:46  LOGON 4213192 1444700 
5 A002 R051 02-00-00 07-30-13 16:00:00 REGULAR 4213333 1444737 
6 A002 R051 02-00-00 08-01-13 00:00:00 REGULAR 4215894 1445274 
7 A002 R051 02-00-00 07-27-13 08:00:00 REGULAR 4209663 1443616 
8 A002 R051 02-00-00 07-28-13 16:00:00 REGULAR 4210775 1443921 
9 A002 R051 02-00-00 07-30-13 00:00:00 REGULAR 4212845 1444369 
10A002 R051 02-00-00 07-30-13 14:02:18 DOOR OPEN 4213192 1444700 
11A002 R051 02-00-00 07-31-13 00:00:00 REGULAR 4214345 1444823 
12A002 R051 02-00-00 08-01-13 08:00:00 REGULAR 4215977 1445362 

Challen ge здесь, что столбцы, которые я хочу «расплавить», имеют разные типы данных. Все прочитанные сообщения очень просты и предполагают, что все расплавленные столбцы имеют один и тот же тип данных и попадут в хорошие пары ключ/значение. Это явно не так.

Я нашел еще одно сообщение, указывающее, что эта реструктуризация может быть выполнена с использованием «замены» из статистики. Я понимаю. Но если dplyr, reshape2 и tidyr нельзя использовать для более сложных реалий реального мира, что такое реальное использование?

Просьба показать, как это сделать с помощью tidyr, dplyr или reshape2.

Спасибо заранее!

ответ

3

Там, наверное, хороший tidyr и/или data.table решение, но вы также можете сделать следующее в базовой R сложить две группы пять столбцов:

names(dat) = gsub("1|2", "", names(dat)) 
rbind(dat[,1:8], dat[,c(1:3,9:13)]) 
 CA UNIT  SCP  DATE  TIME  DESC ENTRIES EXITS 
1 A002 R051 02-00-00 07-27-13 00:00:00 REGULAR 4209603 1443585 
2 A002 R051 02-00-00 07-28-13 08:00:00 REGULAR 4210490 1443821 
3 A002 R051 02-00-00 07-29-13 16:00:00 REGULAR 4211586 1444302 
4 A002 R051 02-00-00 07-30-13 14:01:46  LOGON 4213192 1444700 
5 A002 R051 02-00-00 07-30-13 16:00:00 REGULAR 4213333 1444737 
6 A002 R051 02-00-00 08-01-13 00:00:00 REGULAR 4215894 1445274 
7 A002 R051 02-00-00 07-27-13 08:00:00 REGULAR 4209663 1443616 
8 A002 R051 02-00-00 07-28-13 16:00:00 REGULAR 4210775 1443921 
9 A002 R051 02-00-00 07-30-13 00:00:00 REGULAR 4212845 1444369 
10 A002 R051 02-00-00 07-30-13 14:02:18 DOOR_OPEN 4213192 1444700 
11 A002 R051 02-00-00 07-31-13 00:00:00 REGULAR 4214345 1444823 
12 A002 R051 02-00-00 08-01-13 08:00:00 REGULAR 4215977 1445362 

В вашей Например, у вас есть только два набора из пяти столбцов, которые необходимо укладывать в стек. Если у вас есть больше таких групп, вы могли бы сделать что-то вроде этого, чтобы избежать много жесткого кодирования:

dat = lapply(seq(4,ncol(dat),5), function(i) { 
    tmp = dat[, c(1:3, i:(i+4))] 
    names(tmp) = gsub("[0-9]", "", names(tmp)) 
    tmp 
}) 

dat = do.call(rbind, dat) 
+0

Спасибо! Я никогда бы не подумал об использовании этого. – Windstorm1981

+0

Ну, перефразируя Дэвида Святого Хаббинса в * Это спинальный тап *, «Между умными и глупыми линиями есть тонкая грань». – eipi10

6

Вот вариант с reshape из базы R, если вы посмотрите на ?reshape разделитель по умолчанию . и если вы укажете sep как "", тогда он будет использовать регулярное выражение для разделения имен столбцов, которое равно [A-Za-z][0-9], что вполне подходит вашему делу. Вы можете оставить переменную time и id, если вы не нуждаетесь в них:

reshape(df, varying = 4:13, dir = "long", sep = "") 
 CA UNIT  SCP time  DATE  TIME  DESC ENTRIES EXITS id 
1: A002 R051 02-00-00 1 07-27-13 00:00:00 REGULAR 4209603 1443585 1 
2: A002 R051 02-00-00 1 07-28-13 08:00:00 REGULAR 4210490 1443821 2 
3: A002 R051 02-00-00 1 07-29-13 16:00:00 REGULAR 4211586 1444302 3 
4: A002 R051 02-00-00 1 07-30-13 14:01:46 LOGON 4213192 1444700 4 
5: A002 R051 02-00-00 1 07-30-13 16:00:00 REGULAR 4213333 1444737 5 
6: A002 R051 02-00-00 1 08-01-13 00:00:00 REGULAR 4215894 1445274 6 
7: A002 R051 02-00-00 2 07-27-13 08:00:00 REGULAR 4209663 1443616 1 
8: A002 R051 02-00-00 2 07-28-13 16:00:00 REGULAR 4210775 1443921 2 
9: A002 R051 02-00-00 2 07-30-13 00:00:00 REGULAR 4212845 1444369 3 
10: A002 R051 02-00-00 2 07-30-13 14:02:18 DOOROPEN 4213192 1444700 4 
11: A002 R051 02-00-00 2 07-31-13 00:00:00 REGULAR 4214345 1444823 5 
12: A002 R051 02-00-00 2 08-01-13 08:00:00 REGULAR 4215977 1445362 6 
+0

Спасибо за это. Я думаю, что это лучший способ сделать это, хотя мой вопрос был направлен на лучшее понимание сложных манипуляций с dplyr, tidyr и reshape2. вопрос: используя синтаксис «4:13» для «изменения», как функция знает, чтобы правильно стекировать столбцы? Знает ли это, что мы имеем дело с равным числом и стекем соответственно? – Windstorm1981

+0

Способ 'reshape' заключается в том, что он сначала разделит имена столбцов либо разделителем, либо регулярным выражением, если разделитель не существует, как ваш случай. И столбцы с левой стороны разделенных сопоставленных имен будут уложены в один столбец, а номер правой стороны будет переменной времени. – Psidom

+0

И изменяющийся «4: 13» указывает номера столбцов, которые должны быть уложены в стек, так что только столбцы с 4 по 13 будут разделены на номер группы в конце имен столбцов и уложены в соответствии с первой половиной имени столбца , – Psidom

1

В tidyr, вам нужно gather до тех пор, исправить имена столбцов, а затем spread обратно широкий. Поскольку spread является привередлив показателями, вам необходимо добавить уникальный столбец ID, который dplyr::add_rownames может сделать красиво:

library(tidyr) 
library(dplyr) 

df %>% add_rownames() %>% 
    # gather to long form 
    gather(var, val, DATE1:EXITS2) %>% 
    # separate ID suffix from variable name by position 
    separate(var, c('var', 'id'), sep = -2) %>% 
    # spread back to wide form 
    spread(var, val, convert = TRUE) %>% 
    # clean up extra columns 
    select(-rowname, -id) 

## # A tibble: 12 x 8 
##  CA UNIT  SCP  DATE  DESC ENTRIES EXITS  TIME 
## * <fctr> <fctr> <fctr> <chr>  <chr> <int> <int> <chr> 
## 1 A002 R051 02-00-00 07-27-13 REGULAR 4209603 1443585 00:00:00 
## 2 A002 R051 02-00-00 07-27-13 REGULAR 4209663 1443616 08:00:00 
## 3 A002 R051 02-00-00 07-28-13 REGULAR 4210490 1443821 08:00:00 
## 4 A002 R051 02-00-00 07-28-13 REGULAR 4210775 1443921 16:00:00 
## 5 A002 R051 02-00-00 07-29-13 REGULAR 4211586 1444302 16:00:00 
## 6 A002 R051 02-00-00 07-30-13 REGULAR 4212845 1444369 00:00:00 
## 7 A002 R051 02-00-00 07-30-13  LOGON 4213192 1444700 14:01:46 
## 8 A002 R051 02-00-00 07-30-13 DOOR OPEN 4213192 1444700 14:02:18 
## 9 A002 R051 02-00-00 07-30-13 REGULAR 4213333 1444737 16:00:00 
## 10 A002 R051 02-00-00 07-31-13 REGULAR 4214345 1444823 00:00:00 
## 11 A002 R051 02-00-00 08-01-13 REGULAR 4215894 1445274 00:00:00 
## 12 A002 R051 02-00-00 08-01-13 REGULAR 4215977 1445362 08:00:00 
+0

Спасибо. Мне нужно подробно рассмотреть ваш ответ, чтобы я полностью понял. У меня может быть вопрос или два. – Windstorm1981

2

Мы можем сделать это легко с melt из data.table как это может занять несколько measurepatterns.

library(data.table) 
melt(setDT(df), measure = patterns(c("DATE", "TIME", "DESC", "ENTRIES", 
     "EXITS")), value.name = c('DATE', 'TIME', 'DESC', 'ENTRIES', 
     'EXITS'))[, variable := NULL][] 
#  CA UNIT  SCP  DATE  TIME  DESC ENTRIES EXITS 
#1: A002 R051 02-00-00 07-27-13 00:00:00 REGULAR 4209603 1443585 
#2: A002 R051 02-00-00 07-28-13 08:00:00 REGULAR 4210490 1443821 
#3: A002 R051 02-00-00 07-29-13 16:00:00 REGULAR 4211586 1444302 
#4: A002 R051 02-00-00 07-30-13 14:01:46  LOGON 4213192 1444700 
#5: A002 R051 02-00-00 07-30-13 16:00:00 REGULAR 4213333 1444737 
#6: A002 R051 02-00-00 08-01-13 00:00:00 REGULAR 4215894 1445274 
#7: A002 R051 02-00-00 07-27-13 08:00:00 REGULAR 4209663 1443616 
#8: A002 R051 02-00-00 07-28-13 16:00:00 REGULAR 4210775 1443921 
#9: A002 R051 02-00-00 07-30-13 00:00:00 REGULAR 4212845 1444369 
#10:A002 R051 02-00-00 07-30-13 14:02:18 DOOR OPEN 4213192 1444700 
#11:A002 R051 02-00-00 07-31-13 00:00:00 REGULAR 4214345 1444823 
#12:A002 R051 02-00-00 08-01-13 08:00:00 REGULAR 4215977 1445362 
+0

Спасибо. Я не так хорошо знаком с пакетом data.table, каким бы я хотел быть. Мне нужно подробно рассмотреть ваш ответ, чтобы убедиться, что я это понимаю. – Windstorm1981

Смежные вопросы