2016-01-16 2 views
17

Аргумент drop в dcast (из «reshape2» или «dplyr») может быть полезен при переходе от «длинного» к «широкому «dataat», и вы хотите создавать столбцы даже для комбинаций, которые не существуют в длинной форме.Сделать аргумент `drop` в` dcast` только посмотреть на RHS формулы

Оказывается, что использование drop также влияет на комбинации левой стороны (LHS) формулы, а также на правую сторону (RHS). Таким образом, он также создает дополнительные строки на основе комбинаций значений LHS.

Есть ли способ отменить это поведение?


Вот некоторые примерные данные:

library(data.table) 
DT <- data.table(v1 = c(1.105, 1.105, 1.105, 2.012, 2.012, 2.012), 
       ID = c(1L, 1L, 1L, 2L, 2L, 2L), 
       v2 = structure(c(2L, 3L, 5L, 1L, 2L, 6L), 
           .Label = c("1", "2", "3", "4", "5", "6"), 
           class = "factor"), 
       v3 = c(3L, 2L, 2L, 5L, 4L, 3L)) 

Обратите внимание, что "v2" является factor колонна с 6 уровней. Я по существу хочу, чтобы перейти от «длинных» в ширину», но добавить в столбцах для любых отсутствующих уровней факторов (в данном случае„4“)

reshape обрабатывает форму, но не хватает столбцов:.

reshape(DT, direction = "wide", idvar = c("ID", "v1"), timevar = "v2") 
#  v1 ID v3.2 v3.3 v3.5 v3.1 v3.6 
# 1: 1.105 1 3 2 2 NA NA 
# 2: 2.012 2 4 NA NA 5 3 

dcast ручки добавив недостающие столбцы, но только если есть одно значение на LHS:

dcast(DT, ID ~ v2, value.var = "v3", drop = FALSE) 
# ID 1 2 3 4 5 6 
# 1: 1 NA 3 2 NA 2 NA 
# 2: 2 5 4 NA NA NA 3 

Если имеется несколько значений на LHS, комбинации значений на LHS также расширены вне, а если бы мы использовали CJ или expand.grid, но строки 2 и 3 вообще не интересны для меня:

dcast(DT, ... ~ v2, value.var = "v3", drop = FALSE) 
#  v1 ID 1 2 3 4 5 6 
# 1: 1.105 1 NA 3 2 NA 2 NA 
# 2: 1.105 2 NA NA NA NA NA NA 
# 3: 2.012 1 NA NA NA NA NA NA 
# 4: 2.012 2 5 4 NA NA NA 3 

Это аналогично использованию xtabs в базовом R: ftable(xtabs(v3 ~ ID + v1 + v2, DT)).


Есть ли способ, чтобы dcast знать, что по существу, «Эй. Сочетание значений на LHS являются идентификаторами. Не пытайтесь заполнить их для меня.»

Мой нынешний подход состоит в том, чтобы выполнить три шага, один для свертывания значений LHS, другой для распространения значений RHS, а затем для слияния результата.

merge(DT[, list(v1 = unique(v1)), .(ID)], ## or unique(DT[, c("ID", "v1"), with = FALSE]) 
     dcast(DT, ID ~ v2, value.var = "v3", drop = FALSE), 
     by = "ID")[] 
# ID v1 1 2 3 4 5 6 
# 1: 1 1.105 NA 3 2 NA 2 NA 
# 2: 2 2.012 5 4 NA NA NA 3 

Есть ли лучший подход, который мне не хватает?

+0

Что-то близко (возможно): 'dcast (DT, взаимодействие (v1, ID, падение = TRUE) ~ v2, value.var = "v3", падение = FALSE)'. Тем не менее, вы должны разбить первый столбец. – nicola

+0

@nicola, я подумал об этом, но мне не понравилась возможная потеря верности данных, отсутствие возможности использовать '...' на LHS и потерю имен столбцов. – A5C1D2H2I1M1N2O1R2T1

+0

Возможное решение может позволить двойную логику в 'drop'. Что-то вроде 'drop = c (TRUE, FALSE)', где первое относится к RHS, а второе - к LHS. – Jaap

ответ

7

Только что реализованный в версии данных.table версии v1.9.7, commit 2113, закрывает #1512.

require(data.table) # v1.9.7, commit 2113+ 
dcast(DT, ... ~ v2, value.var = "v3", drop = c(TRUE, FALSE)) 
#  v1 ID 1 2 3 4 5 6 
# 1: 1.105 1 NA 3 2 NA 2 NA 
# 2: 2.012 2 5 4 NA NA NA 3 

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

  • Нет связанных вопросов^_^