R: преобразование данных "короткой формы" в данные "длинной формы" без циклов for? - PullRequest
4 голосов
/ 04 мая 2011

Предположим, у меня есть R-фрейм данных, подобный следующему:

  Subject Session  Property.A Property.B Property.C
1     100       1 -1.22527548 -0.9193751 -1.7501693
2     100      10  2.30627980  1.8940830 -0.8443976
3     100       2  2.33243332 -0.5860868 -4.2074489
4     100       3  0.38130810 -0.7336206  4.8016230
5     100       4  1.44685875  0.5066249  2.0138624
6     100       5  0.08907721 -0.3715202  1.4983700

Я слышал этот стиль фрейма данных, называемый "короткой формой" или "широкой формой".Теперь предположим, что я хочу, чтобы это выглядело так, как я слышал, под названием «длинная форма»:

  Subject Session  Property    Value
1     100       1         A   -1.2252754
2     100       1         B   -0.9193751
3     100       1         C   -1.7501693
4     100       2         A    2.3324333
5     100       2         B   -0.5860868
6     100       2         C   -4.2074489

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

Очевидно, я мог бы выполнить это преобразование с кучей циклов for, но это кажется действительно уродливым, и было бы трудно поддерживать, если/ когда я добавляю больше столбцов свойств.

Есть ли способ сделать это в R с помощью всего лишь нескольких строк кода?Какая-то волшебная комбинация функций, которую я еще не обнаружил?

Ответы [ 3 ]

11 голосов
/ 04 мая 2011

Используйте функцию melt в пакете reshape2:

library(reshape2)
dat.m <- melt(dat, id.vars = c("Subject", "Session"))

Если вам нужно очистить имена столбцов и / или значения для столбца переменных:

#change "variable" to "Property"
names(dat.m)[3] <- "Property"
#Drop "Property." from the column values
dat.m$Property <- gsub("Property\\.", "", dat.m$Property)
4 голосов
/ 04 мая 2011

Мне нравится использовать функции plyr, но функция reshape из базы довольно мощная, как показано на приведенном ниже решении.

# create a dummy data frame
dat = data.frame(
  subject = rep(100, 5),
  session = sample(5, 10, replace = T),
  property.a = rnorm(5),
  property.b = rnorm(5),
  property.c = rnorm(5)
)

# convert wide to long, varying columns are 3:5, separator is "."
dat.long = reshape(dat, direction = 'long', varying = 3:5, sep = ".")
2 голосов
/ 04 мая 2011

изменить пакет для этого отлично подходит для этого, но ... куча циклов не является альтернативой.

возможно, этот пример поучителен ...

longDF <- lapply( 3:4, function(x) cbind(wideDF[1:2], p = names(wideDF)[x], wideDF[x]) )
longDF <- rbind( longDF )

или этот

longDF <- cbind( rep(wideDF[1], 3), rep(wideDF[2], 3), c(wideDF[3], wideDF[4], wideDF[5]) )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...