2013-02-25 2 views
7

У меня есть эта проблема с data.table, которая в последнее время сводит меня с ума. Это похоже на ошибку, но может быть, я не вижу здесь ничего очевидного.data.table НЕ суммируется должным образом по двум столбцам

У меня есть следующий кадр данных:

# First some data 
data <- data.table(structure(list(
    month = structure(c(1356998400, 1356998400, 1356998400, 
         1359676800, 1354320000, 1359676800, 1359676800, 1356998400, 1356998400, 
         1354320000, 1354320000, 1354320000, 1359676800, 1359676800, 1359676800, 
         1356998400, 1359676800, 1359676800, 1356998400, 1359676800, 1359676800, 
         1359676800, 1359676800, 1354320000, 1354320000), class = c("POSIXct", 
                       "POSIXt"), tzone = "UTC"), 
    portal = c(TRUE, TRUE, FALSE, TRUE, 
      TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, 
      TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE 
), 
    satisfaction = c(10L, 10L, 10L, 9L, 10L, 10L, 9L, 10L, 10L, 
        9L, 2L, 8L, 10L, 9L, 10L, 10L, 9L, 10L, 10L, 10L, 9L, 10L, 9L, 
        10L, 10L)), 
        .Names = c("month", "portal", "satisfaction"), 
        row.names = c(NA, -25L), class = "data.frame")) 

Я хочу суммировать его как portal и month. Суммируя со старым добрым tapply работает, как ожидалось - я получаю 3x2 матрицу с результатами для дек-2012 и январь-февраль 2013 года:

> tapply(data$satisfaction, list(data$month, data$portal), mean) 
      FALSE  TRUE 
2012-12-01 8.5 8.000000 
2013-01-01 10.0 10.000000 
2013-02-01 9.0 9.545455 

Резюмируя с by аргументом data.table не:

> data[, mean(satisfaction), by = 'month,portal'] 
    month  portal  V1 
1: 2013-01-01 FALSE 10.000000 
2: 2013-02-01 TRUE 9.000000 
3: 2013-01-01 TRUE 10.000000 
4: 2012-12-01 FALSE 8.500000 
5: 2012-12-01 TRUE 7.333333 
6: 2013-02-01 TRUE 9.666667 
7: 2013-02-01 FALSE 9.000000 
8: 2012-12-01 TRUE 10.000000 

Как вам см., он возвращает таблицу данных с значения, а не как ожидалось; где portal == TRUE и month == 2012-02-01 дублируются, например.

Интересно, если я ограничить данные этого только до 2013 года, в все работает, как ожидалось:

> data[month >= ymd(20130101), mean(satisfaction), by = 'month,portal'] 
     month portal  V1 
1: 2013-01-01 TRUE 10.000000 
2: 2013-01-01 FALSE 10.000000 
3: 2013-02-01 TRUE 9.545455 
4: 2013-02-01 FALSE 9.000000 

Я озадачен за верю :). Может кто-нибудь, пожалуйста, помогите мне?

+0

Использовать 'by = list (month, portal)' – Andrie

+0

Во-первых, 'data [, mean (satisfaction), by = list (month, portal)]' производит тот же (неверный) результат. Во-вторых, в соответствии с помощью справки 'data.table' поддерживаются оба синтаксиса:« by - одиночное имя без кавычек, список() выражений имен столбцов, одиночная символьная строка, содержащая имена столбцов, разделенных запятыми, или символьный вектор имена столбцов.« –

+3

Кажется, что работает преобразование столбца POSIX в Date (' as.Date'). Я думаю, что data.table (правильно? Неправильно?) Разделяет некоторые слова о том, являются ли некоторые из этих дат «равными». – joran

ответ

8

Это известная проблема, которая была решена в data.table 1.8.7 (а не в CRAN еще на момент написания этой статьи).

От data.table NEWS:

BUG FIXES 

    <...> 

o setkey could sort 'double' columns (such as POSIXct) incorrectly when not the 
    last column of the key, #2484. In data.table's C code : 
     x[a] > x[b]-tol 
    should have been : 
     x[a]-x[b] > -tol [or x[b]-x[a] < tol ] 
    The difference may have been machine/compiler dependent. Many thanks to statquant 
    for the short reproducible example. Test added. 

После обновления до 1.8.7 с install.packages("data.table", repos="http://R-Forge.R-project.org"), все работает, как ожидалось.

5

Проблема, похоже, связана с сортировкой. Когда я загружаю data и сделать setkey:

setkey(data, "month", "portal") 

# > data 
#   month portal satisfaction 
# 1: 2012-12-01 TRUE   10 
# 2: 2012-12-01 FALSE   9 
# 3: 2012-12-01 FALSE   8 
# 4: 2012-12-01 TRUE   2 
# 5: 2012-12-01 TRUE   10 
# 6: 2012-12-01 TRUE   10 
# 7: 2013-01-01 TRUE   10 
# 8: 2013-01-01 TRUE   10 
# 9: 2013-01-01 TRUE   10 
# 10: 2013-01-01 TRUE   10 
# 11: 2013-01-01 TRUE   10 
# 12: 2013-01-01 TRUE   10 
# 13: 2013-01-01 FALSE   10 
# 14: 2013-02-01 TRUE   9 
# 15: 2013-02-01 TRUE   9 
# 16: 2013-02-01 FALSE   9 
# 17: 2013-02-01 TRUE   10 
# 18: 2013-02-01 TRUE   10 
# 19: 2013-02-01 TRUE   10 
# 20: 2013-02-01 TRUE   10 
# 21: 2013-02-01 TRUE   10 
# 22: 2013-02-01 TRUE   9 
# 23: 2013-02-01 TRUE   10 
# 24: 2013-02-01 TRUE   9 
# 25: 2013-02-01 TRUE   9 
#   month portal satisfaction 

Вы видите, что portal столбец не отсортирован. Когда я снова сделать setkey,

setkey(data, "month", "portal") 

# I get this warning message: 
Warning message: 
In setkeyv(x, cols, verbose = verbose) : 
    Already keyed by this key but had invalid row order, key rebuilt. 
    If you didn't go under the hood please let datatable-help know so 
    the root cause can be fixed. 

Теперь, data колонны кажутся отсортирован по ключевым столбцам:

# > data 
#   month portal satisfaction 
# 1: 2012-12-01 FALSE   9 
# 2: 2012-12-01 FALSE   8 
# 3: 2012-12-01 TRUE   10 
# 4: 2012-12-01 TRUE   2 
# 5: 2012-12-01 TRUE   10 
# 6: 2012-12-01 TRUE   10 
# 7: 2013-01-01 FALSE   10 
# 8: 2013-01-01 TRUE   10 
# 9: 2013-01-01 TRUE   10 
# 10: 2013-01-01 TRUE   10 
# 11: 2013-01-01 TRUE   10 
# 12: 2013-01-01 TRUE   10 
# 13: 2013-01-01 TRUE   10 
# 14: 2013-02-01 FALSE   9 
# 15: 2013-02-01 TRUE   9 
# 16: 2013-02-01 TRUE   9 
# 17: 2013-02-01 TRUE   10 
# 18: 2013-02-01 TRUE   10 
# 19: 2013-02-01 TRUE   10 
# 20: 2013-02-01 TRUE   10 
# 21: 2013-02-01 TRUE   10 
# 22: 2013-02-01 TRUE   9 
# 23: 2013-02-01 TRUE   10 
# 24: 2013-02-01 TRUE   9 
# 25: 2013-02-01 TRUE   9 
#   month portal satisfaction 

Итак, это, кажется, проблема с sortting POSIXct + logical типов?

data[, mean(satisfaction), by=list(month, portal)] 

#   month portal  V1 
# 1: 2012-12-01 FALSE 8.500000 
# 2: 2012-12-01 TRUE 8.000000 
# 3: 2013-01-01 FALSE 10.000000 
# 4: 2013-01-01 TRUE 10.000000 
# 5: 2013-02-01 FALSE 9.000000 
# 6: 2013-02-01 TRUE 9.545455 

Я поэтому думаю, что есть ошибка.

+2

Да, я как раз собирался оставить комментарий, говоря, что если @MatthewDowle не весит этого в один день или два, OP должен, вероятно, опубликовать этот вопрос в списке рассылки data.table. – joran

+1

Ага! Спасибо Аруну, это действительно так. Я сообщу об этом как об ошибке в списке рассылки. Мы будем ждать ответа Мэтью на всякий случай, прежде чем принимать ваш ответ. –

+0

@joran, победитель, конечно. – Arun

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