2016-02-27 3 views
2

У меня есть новая проблема с этими данными. Поскольку мои полные данные имеют вид, как этогоОбратитесь к предыдущей строке в data.table в R, с условием

a=data.table(A=c(1:10),B=c(1,2,0,2,0,0,3,4,0,2),C=c(2,3,1,4,5,3,6,7,2,2),D=c(1,1,1,1,1,2,2,2,2,2)) 


#  A B C D 
# 1: 1 1 2 1 
# 2: 2 2 3 1 
# 3: 3 0 1 1 
# 4: 4 2 4 1 
# 5: 5 0 5 1 
# 6: 6 0 3 2 
# 7: 7 3 6 2 
# 8: 8 4 7 2 
# 9: 9 0 2 2 
#10: 10 2 2 2 

Теперь я хочу, чтобы создать новый столбец, который вычисляет количество значений кратны с B/C из шкафа предыдущего ряда, до тех пор, как Б а не 0. Например, в строке 2 я могу рассчитать D = 2 * (1/2). Однако в строке 4 она должна быть 4 * (2/3), она не может быть 4 * (0/1). Я использую

a[, D:= {i1 <- (NA^!B) 
list(A*shift(na.locf(i1*B))/shift(na.locf(i1*C)))},by=d] 

, как Akrun вчера рекомендовал. Он не работает, когда я рассчитываю его по группе. Результат такой:

A B C d  D 
# 1: 1 1 2 1  NA 
# 2: 2 2 3 1 1.000000 
# 3: 3 0 1 1 2.000000 
# 4: 4 2 4 1 2.666667 
# 5: 5 0 5 1 2.500000 
# 6: 6 0 3 2  NA 
# 7: 7 3 6 2 3.500000 
# 8: 8 4 7 2 4.571429 
# 9: 9 0 2 2 5.142857 
# 10: 10 2 2 2  NA 

Кто-нибудь знает, в чем проблема здесь? Ошибка - это длинная длина объекта не кратна короткой длине объекта.

+0

Что бы выход для первого элемента D? – akrun

+0

Выход для первого элемента D будет NA –

ответ

3

Мы можем заменить элементы в 'B', 'C', которые соответствуют значению '0' в 'B' как NA. Используйте na.locf от zoo, чтобы заменить эти значения NA прежними элементами не-NA, shift элементов (по умолчанию он дает lag из 1), разделите измененные столбцы «B» на «C», а затем умножьте на «A», , Назначьте (:=) вывод в новый столбец «D».

library(zoo) 
a[B==0, c('B', 'C'):=list(NA, NA)] 
a[, c('B', 'C'):= na.locf(.SD), .SDcols=B:C] 
a[, D:= {tmp <- shift(.SD[, 2:3, with=FALSE]) 
      A*(tmp[[1]]/tmp[[2]])}] 

Или мы можем сделать его компактным. Мы получаем логический вектор (!B), который проверяет '0' элементы в 'B', преобразует это в вектор из 1s и NA (NA^), умножая на столбцы 'B' и 'C', так что 1s заменяются на соответствующие элементы в этих столбцах, тогда как NA остается таковым. Сделайте na.locf (как и раньше), shift, а затем выполните умножение/деление.

a[, D:= {i1 <- (NA^!B) 
    list(A*shift(na.locf(i1*B))/shift(na.locf(i1*C)))}] 

Или вместо вызова shift/na.locf два раза

a[, D:= {i1 <- (NA^!B) 
     tmp <- shift(na.locf(i1*.SD)) 
     a[['A']]*(tmp[[1]]/tmp[[2]])}, .SDcols=B:C] 
+1

Спасибо. Вы действительно решаете мои проблемы. Это действительно компактно. –

+0

Привет, @akrun, не могли бы вы взглянуть? –

+0

@ThanhQuang Вам может понадобиться '... na.locf (i1 * B), na.rm = FALSE)/shift (na.locf (i1 * C, na.rm = FALSE) ...' – akrun

3

Это может быть сделано с помощью прокатки присоединиться:

a[, row := .I] 
a[, B/C, by=row][V1 != 0][a, A*shift(V1), on="row", roll=TRUE] 
# [1]  NA 1.000000 2.000000 2.666667 2.500000 3.000000 3.500000 4.000000 
# [9] 5.142857 5.714286 
Смежные вопросы