2017-01-27 7 views
1

Ich habe einen Datenrahmen und möchte für jede Zeile die Summe jeder zweiten Zelle (beginnend mit der zweiten Zelle), deren linker Nachbar größer als Null ist. Hier ein Beispiel:R, bedingte Summierung jeder zweiten Zelle in jeder Zeile

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) 

Das gibt:

> 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 

Für die erste Reihe der richtige Summe 0 (der linke Nachbarn von 1 -2 und dem linken Nachbarn von 5 ist auch -2) ; für die Sekunde ist es 8; für das dritte ist es 3; für die vierte ist es wieder 8.

Ich möchte es ohne Schleifen zu tun, so versuchte ich es mit sum() und which() wie in Conditional Sum in R, aber konnte keinen Weg durch.

Antwort

2

Wir unterteilen den Datensatz für alternierende Spalten mithilfe des Recyclingvektors (c(TRUE, FALSE)), um die 1., 3., ... usw. Spalten des Datensatzes zu erhalten. Konvertieren Sie ihn in einen logischen Vektor, indem Sie prüfen, ob er größer als 0 ist. (> 0), dann multiplizieren Sie die Werte mit der zweiten Teilmenge von alternierenden Spalten, dh. Spalten 2, 4 usw. mit dem Recycling-Vektor (c(FALSE, TRUE)). Die Idee ist, dass, wenn es in der linken Spalte Werte gibt, die kleiner als 0 sind, es in der logischen Matrix FALSE ist und durch Multiplikation mit der anderen Teilmenge auf 0 gezwungen wird. Schließlich machen die rowSums die erwartete Ausgabe

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

Es kann auch mit seq

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

Oder eine andere Option Reduce ist mit

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

Map Dies funktioniert gut ersetzt bekommen werden aber ich verstehe nicht wie. Was macht der '*' Operator? – Joe

+0

@Joe Es ist der Operator für die Multiplikation, so wie die entsprechenden Werte für andere logische Matrix auf 0 für FALSE konvertieren – akrun

Verwandte Themen