2017-01-27 8 views
1

У меня есть кадр данных и хочу, чтобы для каждой строки была сумма каждой второй ячейки (начиная со второй ячейки), левый сосед которой больше нуля. Вот пример:R, условное суммирование каждой второй ячейки в каждой строке

a <- c(-2,1,1,-2) 
b <- c(1,2,3,4) 
c <- c(-2,1,-1,2) 
d <- c(5,6,7,8) 
df <- data.frame(a,b,c,d) 

Это дает:

> df 
    a b c d 
1 -2 1 -2 5 
2 1 2 1 6 
3 1 3 -1 7 
4 -2 4 2 8 

В первой строке правильная сумма 0 (левый сосед 1 -2 и левого соседа 5 также -2) ; для второго - 8; для третьего - 3; для четвёртого это снова 8.

Я хочу сделать это без петель, так что я пробовал с sum() и which() как в Conditional Sum in R, но не может найти путь до конца.

ответ

2

Мы подмножество набора данных для чередующихся столбцов с использованием вектора рециркуляции (c(TRUE, FALSE)), чтобы получить 1, 3, ... и т.д. столбцы набора данных, преобразовать его в логический вектор, проверяя, является ли оно больше 0 (> 0), затем умножьте значения на второе подмножество чередующихся столбцов, т. е. столбцы 2, 4 и т. д., используя вектор рециркуляции (c(FALSE, TRUE)). Идея состоит в том, что если в левом столбце есть значения, которые меньше 0, в логической матрице будет FALSE, и он будет принужден к 0 путем умножения на другое подмножество. И, наконец, сделать rowSums, чтобы получить ожидаемый результат

rowSums((df[c(TRUE, FALSE)]>0)*df[c(FALSE, TRUE)]) 
#[1] 0 8 3 8 

Он может быть также заменен seq

rowSums((df[seq(1, ncol(df), by = 2)]>0)*df[seq(2, ncol(df), by = 2)]) 
#[1] 0 8 3 8 

Или другой вариант является Reduce с Map

Reduce(`+`, Map(`*`, lapply(df[c(TRUE, FALSE)], `>`, 0), df[c(FALSE, TRUE)])) 
#[1] 0 8 3 8 
+0

Это прекрасно работает , но я не понимаю, как это сделать. Что делает оператор '*'? – Joe

+0

@Joe Это оператор умножения, который преобразует соответствующие значения в 0 для FALSE в другой логической матрице – akrun