2015-05-20 2 views
3

У меня есть набор данных, который выглядит, чтоПетля подвести итоги наблюдения больше, чем предмет в R

set.seed(100) 
da <- data.frame(exp = c(rep("A", 4), rep("B", 4)), diam = runif(8, 10, 30)) 

Для каждой строки в наборе данных я хочу подвести итоги наблюдения (диам), которые больше, чем diam в определенной строке и включены в уровень «exp». Для этого я сделал петлю:

da$d2 <- 0 
for (i in 1:length(da$exp)){ 
for (j in 1:length(da$exp)){ 
    if (da$diam[i] < da$diam[j] & da$exp[i] == da$exp[j]){ 
    da$d2[i] = da$d2[i] + da$diam[j]} 
} 
} 

Лопп прекрасно работает, и я получил результаты

exp  diam  d2 
1 A 16.15532 21.04645 
2 A 15.15345 37.20177 
3 A 21.04645 0.00000 
4 A 11.12766 52.35522 
5 B 19.37099 45.92347 
6 B 19.67541 26.24805 
7 B 26.24805 0.00000 
8 B 17.40641 65.29445 

Однако, мой реальный набор данных гораздо больше, чем (> 40000 строк и> 100 ехр уровни), поэтому цикл идет очень медленно. Надеюсь, что для облегчения расчетов можно использовать некоторую функцию.

ответ

5

Если вы не требуют первоначального порядка в результате вы могли бы сделать это достаточно эффективно, как это:

library(data.table) 
setorder(setDT(da), exp, -diam) 
da[, d2 := cumsum(diam) - diam, by = exp] 

da 
# exp  diam  d2 
#1: A 21.04645 0.00000 
#2: A 16.15532 21.04645 
#3: A 15.15345 37.20177 
#4: A 11.12766 52.35522 
#5: B 26.24805 0.00000 
#6: B 19.67541 26.24805 
#7: B 19.37099 45.92347 
#8: B 17.40641 65.29445 

Использование dplyr, это было бы:

library(dplyr) 
da %>% 
    arrange(exp, desc(diam)) %>% 
    group_by(exp) %>% 
    mutate(d2 = cumsum(diam) - diam) 
+0

Очень хорошее решение. Вероятно, вы можете пропустить упорядочение с помощью 'exp', но результат не будет таким приятным. Или вы могли бы сделать 'keyby = exp' вместо этого. –

+0

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

+0

Решения отлично работают на моем большом наборе данных. Благодаря! – Mateusz1981

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