2016-11-01 2 views
0

У меня была функция, чтобы найти максимальное значение до текущего номера строки.примените специальную функцию к определенному столбцу, по которому можно поместить группу в data.table

dt<- setDT(copy(mtcars),keep.rownames = TRUE) 

apply(as.matrix(dt$rn), 1, function(x) { 
index = as.numeric(ifelse(match(x, dt$rn) == 1, 2, match(x, dt$rn))) 
max(dt[1:index-1,"mpg",with = FALSE]) 
}) 
    # [1] 21.0 21.0 21.0 22.8 22.8 22.8 22.8 22.8 24.4 24.4 24.4 24.4 24.4 24.4 24.4 24.4 24.4 24.4 32.4 32.4 33.9 33.9 33.9 33.9 33.9 33.9 33.9 33.9 33.9 33.9 33.9 
    # [32] 33.9 

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

dt[,max:=lapply(.SD,function(x){ 
     index = as.numeric(ifelse(match(x,dt$rn) == 1, 2, match(x, dt$rn))) 
     return(max(dt[1:index-1,"mpg",with = FALSE])) 
     }),by = gear,.SDcols = "rn"] 

Я чувствую, что может быть что-то не хватает ..

+3

Ваша функция может быть заменена на простое 'cummax (dt $ mpg)' –

+0

@DavidArenburg op отсутствует в parens в '1: index-1', правильно? так что исправление, которое дает мне разницу в одном значении – rawr

+0

@rawr да, я думаю, что вы правы –

ответ

0

в растворе data.table

dt[, currMax := cummax(shift(mpg, fill = -Inf)), by = gear], 
head(dt) 
#      rn mpg cyl disp hp drat wt qsec vs am gear carb currMax 
# 1:   Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 -Inf 
# 2:  Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 21.0 
# 3:  Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 21.0 
# 4: Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 -Inf 
# 5: Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 21.4 
# 6:   Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 21.4 

Спасибо @DavidArenburg за редактирование.

+2

Нет, это не похоже на решение 'data.table', а скорее копирование/вставка из комментариев/другого ответа. 'data.table' не имеет функции' lag'. Одним из возможных решений может быть «dt [, currMax: = cummax (shift (mpg, fill = -Inf)), by = gear]', например –

+0

Не мое нисходящее отношение кстати. –

1

Не уверен в data.table, но относительно проста в dplyr. Установите group_by, затем mutate, который работает в группе.

res <- 
    mtcars %>% 
    group_by(gear) %>% 
    mutate(currMax = cummax(mpg)) 

Вот подмножество результата, достигнуто с:

res %>% 
    select(gear, mpg, currMax) %>% 
    slice(1:3) 

Чтобы ограничить результат соответствующих столбцов и первых трех строк из каждой группы.

gear mpg currMax 
    <dbl> <dbl> <dbl> 
1  3 21.4 21.4 
2  3 18.7 21.4 
3  3 18.1 21.4 
4  4 21.0 21.0 
5  4 21.0 21.0 
6  4 22.8 22.8 
7  5 26.0 26.0 
8  5 30.4 30.4 
9  5 15.8 30.4 

Если вы хотите, максимальное значение для каждой строки до, но не включая, текущую строку, вам нужно будет сделать немного больше манипуляционным. В частности, cummax не имеет встроенной обработки NA и по определению ваше первое значение должно быть NA. Итак, я написал небольшую функцию, которая временно меняет NA на отрицательную бесконечность, а затем возвращает эти записи в NA (это будет проблемой тогда и только тогда, когда ваши данные на самом деле имеют-Inf значения, и даже тогда, только если они первые в данных). Затем я использовать эту функцию в качестве ведомой макс:

my_cummax <- function(x){ 
    x <- ifelse(is.na(x), -Inf, x) 
    out <- cummax(x) 
    out[out == -Inf] <- NA 
    return(out) 
} 

mtcars %>% 
    group_by(gear) %>% 
    mutate(currMax = cummax(mpg) 
     , trailMax = my_cummax(lag(mpg))) 

Ограниченное ломтик возвращения, подобно выше, показывает:

gear mpg currMax trailMax 
    <dbl> <dbl> <dbl> <dbl> 
1  3 21.4 21.4  NA 
2  3 18.7 21.4  21.4 
3  3 18.1 21.4  21.4 
4  4 21.0 21.0  NA 
5  4 21.0 21.0  21.0 
6  4 22.8 22.8  21.0 
7  5 26.0 26.0  NA 
8  5 30.4 30.4  26.0 
9  5 15.8 30.4  30.4 
+1

'dt [,. (mpg, currMax = cummax (mpg)), by = gear]'? Это просто обычная операция группы –

+0

@MarkPeterson Я не проверял ответ перед внесением изменений. Кроме того, это не только максимальное значение внутри группы. но до текущего индекса руды в этой группе, следовательно, может быть 1: index-1 – theArun

+0

@DavidArenburg Sure - я не предлагал решение data.table, потому что это не то, что я использую. Если это будет работать, не стесняйтесь публиковать в качестве альтернативного ответа. –

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