R: Найти и добавить отсутствующие (/ не существующие) строки во временном фрейме данных - PullRequest
14 голосов
/ 03 апреля 2012

Я борюсь со следующим.

Если есть (большой) фрейм данных со следующим:

  • несколько столбцов, для которых комбинация столбцов является «уникальной» комбинацией, скажем, ID
  • столбец, связанный со временем
  • столбец, связанный с мерой

Я хочу убедиться, что для каждого уникального идентификатора для каждого временного интервала мера доступна во фрейме данных. И если это не так, я хочу добавить 0 (или NA) меру для этого времени / ID.

Чтобы проиллюстрировать проблему, создайте следующий test фрейм данных:

test <- data.frame(
    YearWeek   =rep(c("2012-01","2012-02"),each=4),
    ProductID  =rep(c(1,2), times=4),
    CustomerID =rep(c("a","b"), each=2, times=2),
    Quantity   =5:12
)[1:7,]

  YearWeek ProductID CustomerID Quantity
1  2012-01         1          a        5
2  2012-01         2          a        6
3  2012-01         1          b        7
4  2012-01         2          b        8
5  2012-02         1          a        9
6  2012-02         2          a       10
7  2012-02         1          b       11

Восьмой ряд пропущен специально. Таким образом, я моделирую «отсутствующее значение» (отсутствует Quantity) для идентификатора «2-b» (ProductID-CustomerID) для значения времени «2012-02».

Я хочу настроить data.frame таким образом, чтобы для всех значений времени (они известны, в данном примере только «2012-01» и «2012-02») для всех ID-комбинаций (они не известны заранее, но это «все уникальные комбинации идентификаторов в кадре данных», то есть уникальный набор в столбцах идентификаторов), количество доступно в кадре данных.

Это должно привести к этому примеру (если мы выберем NA для отсутствующего значения, обычно я хочу иметь контроль над этим):

  YearWeek ProductID CustomerID Quantity
1  2012-01         1          a        5
2  2012-01         2          a        6
3  2012-01         1          b        7
4  2012-01         2          b        8
5  2012-02         1          a        9
6  2012-02         2          a       10
7  2012-02         1          b       11
8  2012-02         2          b       NA

Конечная цель - создать временные ряды для этих комбинаций идентификаторов, и поэтому я хочу иметь количественные значения для всех значений времени. Мне нужно делать разные агрегации (вовремя) и использовать разные уровни идентификаторов из большого набора данных

Я пробовал несколько вещей, например, с melt и cast из пакета reshape. Но пока мне это не удалось. Следующим шагом является создание функции с циклами for и т. Д., Но это не очень полезно с точки зрения производительности.

Может быть, есть более простой способ мгновенного создания временных рядов с указанием data.frame вроде test. У кого-нибудь есть идеи по этому поводу?

Заранее спасибо!

Обратите внимание, что в реальной задаче имеется более двух «столбцов идентификаторов».


EDIT:

Я должен описать проблему дальше. Существует разница между столбцом time и столбцом ID. Первый (и отличный!) Ответ на вопрос Джоран , возможно, не получил четкого понимания того, что я хочу (и приведенный мной пример не прояснил разницу). Я сказал выше:

для всех ID-комбинаций (они не известны заранее, но это все уникальные комбинации идентификаторов в кадре данных », таким образом, уникальный набор Столбцы идентификаторов)

Поэтому я хочу не «все возможные комбинации идентификаторов», а «все комбинации идентификаторов в данных». Для каждой из этих комбинаций я хочу значение для каждого уникального значения времени.

Позвольте мне прояснить, расширив test до test2 следующим образом

> test2 <- rbind(test, c("2012-02", 3, "a", 13))
> test2
  YearWeek ProductID CustomerID Quantity
1  2012-01         1          a        5
2  2012-01         2          a        6
3  2012-01         1          b        7
4  2012-01         2          b        8
5  2012-02         1          a        9
6  2012-02         2          a       10
7  2012-02         1          b       11
8  2012-02         3          a       13

Это означает, что я хочу, чтобы в результирующем фрейме данных не было комбинации идентификаторов «3-b», поскольку эта комбинация не находится в пределах test2. Если я использую метод первого ответа, я получу следующее:

> vals2 <- expand.grid(YearWeek = unique(test2$YearWeek),
                       ProductID = unique(test2$ProductID),
                       CustomerID = unique(test2$CustomerID))

> merge(vals2,test2,all = TRUE)
   YearWeek ProductID CustomerID Quantity
1   2012-01         1          a        5
2   2012-01         1          b        7
3   2012-01         2          a        6
4   2012-01         2          b        8
5   2012-01         3          a     <NA>
6   2012-01         3          b     <NA>
7   2012-02         1          a        9
8   2012-02         1          b       11
9   2012-02         2          a       10
10  2012-02         2          b     <NA>
11  2012-02         3          a       13
12  2012-02         3          b     <NA>

Так что я не хочу, чтобы строки 6 и 12 были здесь.

Чтобы преодолеть эту проблему, я нашел решение в следующем. Здесь я разделил «уникальный столбец времени» и «комбинацию уникальных идентификаторов». Таким образом, разница с вышеупомянутым состоит в слове «комбинация», а не в каждом столбце идентификатора.

> temp_merge <- merge(unique(test2["YearWeek"]),
                      unique(test2[c("ProductID", "CustomerID")]))

> merge(temp_merge,test2,all = TRUE)
   YearWeek ProductID CustomerID Quantity
1   2012-01         1          a        5
2   2012-01         1          b        7
3   2012-01         2          a        6
4   2012-01         2          b        8
5   2012-01         3          a     <NA>
6   2012-02         1          a        9
7   2012-02         1          b       11
8   2012-02         2          a       10
9   2012-02         2          b     <NA>
10  2012-02         3          a       13

Какие комментарии к этому?

Это элегантный способ или есть лучшие способы?

1 Ответ

20 голосов
/ 03 апреля 2012

Используйте expand.grid и merge:

vals <- expand.grid(YearWeek = unique(test$YearWeek),
                    ProductID = unique(test$ProductID),
                    CustomerID = unique(test$CustomerID))
> merge(vals,test,all = TRUE)
  YearWeek ProductID CustomerID Quantity
1  2012-01         1          a        5
2  2012-01         1          b        7
3  2012-01         2          a        6
4  2012-01         2          b        8
5  2012-02         1          a        9
6  2012-02         1          b       11
7  2012-02         2          a       10
8  2012-02         2          b       NA

* Факты NA могут быть заменены по факту любыми значениями, которые вы выберете, используя поднаборы и is.na.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...