R: data.table .динамические агрегации по столбцам столбцов даты

Я пытаюсь выполнить агрегат min/max для динамически выбранного столбца в таблице data.table. Он отлично работает для столбцов numeric, но я не могу заставить его работать с столбцами Date, если не создам временный столбец data.table.

Это работает, когда я использую имя:

dt <- data.table(Index=1:31, Date = seq(as.Date('2015-01-01'), as.Date('2015-01-31'), by='days'))
dt[, .(minValue = min(Date), maxValue = max(Date))]
# minValue   maxValue
# 1: 2015-01-01 2015-01-31

Это не работает, когда я использую with=FALSE:

colName = 'Date'
dt[, .(minValue = min(colName), maxValue = max(colName)), with=F]
# Error in `[.data.table`(dt, , .(minValue = min(colName), maxValue = max(colName)),  : 
# could not find function "."

Я могу использовать .SDcols в числовом столбце:

colName = 'Index'
dt[, .(minValue = min(.SD), maxValue = max(.SD)), .SDcols=colName]
#   minValue maxValue
#  1:        1       31

Но я получаю сообщение об ошибке, когда делаю то же самое для столбца Date:

colName = 'Date'
dt[, .(minValue = min(.SD), maxValue = max(.SD)), .SDcols=colName]
# Error in FUN(X[[i]], ...) : 
#   only defined on a data frame with all numeric variables

Если я использую lapply(.SD, min) или sapply(), даты заменяются числами.

Следующее работает и, похоже, не тратит память впустую и работает быстро. есть что-нибудь получше?

a <- dt[, colName, with=F]
setnames(a, 'a')
a[, .(minValue = min(a), maxValue = max(a))]

person Jim Cutler    schedule 07.11.2015    source источник
comment
Краткий ответ: используйте .SD[[1]], потому что .SD — это список векторов, и вы хотите использовать в нем первый вектор. Длинный ответ: вы, кажется, нашли какую-то странную лазейку, где data.frame всех числовых столбцов может иметь свои max и min; и я бы не стал основываться на этом странном исключении.   -  person Frank    schedule 08.11.2015


Ответы (1)


При первой попытке:

dt[, .(minValue = min(colName), maxValue = max(colName)), with=F]
# Error in `[.data.table`(dt, , .(minValue = min(colName), maxValue = max(colName)),  : 
# could not find function "."

Вы должны просто прочитать Введение в data.table, чтобы понять, что with= означает. Это проще, если вы знакомы с функцией with() из базы R.

На втором:

dt[, .(minValue = min(.SD), maxValue = max(.SD)), .SDcols=colName]
# Error in FUN(X[[i]], ...) : 
#   only defined on a data frame with all numeric variables

Это похоже на проблему с min() и max() в data.frame/data.table со столбцом с атрибутами. Вот МРЭ.

df = data.frame(x=as.Date("2015-01-01"))
min(df)
# Error in FUN(X[[i]], ...) : 
#   only defined on a data frame with all numeric variables

Чтобы ответить на ваш вопрос, вы можете использовать get():

dt[, .(min = min(get(colName)), max = max(get(colName)))]

Или, как предложил @Frank, оператор [[ для подмножества столбца:

dt[, .(min = min(.SD[[colName]]), max = max(.SD[[colName]]))]

Пока еще нет лучшего способа применения .SD к нескольким функциям (потому что в базе R, похоже, нет одного AFAICT, а data.table пытается максимально использовать базовые функции R). Для решения этой проблемы существует FR #1063. Если/когда это будет реализовано, то можно было бы сделать, например:

# NOTE: not yet implemented, FR #1063
dt[, colwise(.SD, min, max), .SDcols = colName]
person Arun    schedule 08.11.2015
comment
Размышляя об этом,... неуклюжий обходной путь для случая OP - это dcast(dt, .~., value.var="Date", fun=list(min,max)) или dcast(dt, .~., value.var=names(dt), fun=list(min,max)) для одновременного выполнения обеих переменных. - person Frank; 08.11.2015