2016-11-09 4 views
2

mit Ich habe folgende Datenrahmen df:Mutierende mehrere Spalten in einem Datenrahmen dplyr

v1 v2 v3 v4 
1 1 5 7 4 
2 2 6 10 3 

Und ich möchte folgende Datenrahmen df2 Multiplikation Spalten v1 * v3 und v2 * v4 erhalten:

v1 v2 v3 v4 v1v3 v2v4 
1 1 5 7 4 7 20 
2 2 6 10 3 20 18 

Wie kann ich das mit dplyr tun? Mit mutate_each?

Ich brauche eine Lösung, die auf eine große Anzahl von Variablen verallgemeinert werden kann und nicht nur 4 (v1 bis v4). Diese ist der Code, um das Beispiel zu generieren:

v1 <- c(1, 2) 
v2 <- c(5,6) 
v3 <- c(7, 10) 
v4 <- c(4, 3) 
df <- data.frame(v1, v2, v3, v4) 
v1v3 <- c(v1 * v3) 
v2v4 <- c(v2 * v4) 
df2 <- cbind(df, v1v3, v2v4) 
+0

'df%>% mutieren (v1v3 = v1 * v3)%>% mutieren (v2v4 = v2 * v4)' –

+0

ich meine Frage bearbeitet. Ich brauche eine Antwort, die auf eine beliebige Anzahl von Variablen verallgemeinert werden kann, ohne sie alle zu schreiben. – sbac

+0

Sie möchten also Werte in alternativen Spalten multiplizieren? –

Antwort

8

Sie sind wirklich nah dran.

df2 <- 
    df %>% 
    mutate(v1v3 = v1 * v3, 
      v2v4 = v2 * v4) 

so eine schöne einfache Sprache, oder? Dank @Facottons Zeiger auf diese Antwort:: Um dieses Problem zu lösen https://stackoverflow.com/a/34377242/5088194, hier ist ein ordentlich Ansatz

Für weitere große Tricks bitte here.

EDIT zu sehen. Es verhindert, dass in jeder neuen Spalte eine Zeile mit hartem Code geschrieben werden muss. Während es ein wenig ausführlicher ist als der Ansatz, ist die Logik zumindest sofort transparenter/lesbarer. Es ist auch erwähnenswert, dass es mindestens halb so viele Zeilen geben muss wie Spalten vorhanden sind, damit dieser Ansatz funktioniert.

# prep the product column names (also acting as row numbers) 
df <- 
    df %>% 
    mutate(prod_grp = paste0("v", row_number(), "v", row_number() + 2)) 

# converting data to tidy format and pairing columns to be multiplied together. 
tidy_df <- 
    df %>% 
    gather(column, value, -prod_grp) %>% 
    mutate(column = as.numeric(sub("v", "", column)), 
      pair = column - 2) %>% 
    mutate(pair = if_else(pair < 1, pair + 2, pair)) 

# summarize the products for each column 
prod_df <- 
    tidy_df %>% 
    group_by(prod_grp, pair) %>% 
    summarize(val = prod(value)) %>% 
    spread(prod_grp, val) %>% 
    mutate(pair = paste0("v", pair, "v", pair + 2)) %>% 
    rename(prod_grp = pair) 

# put the original frame and summary frames together 
final_df <- 
    df %>% 
    left_join(prod_df) %>% 
    select(-prod_grp) 
+6

Stellen Sie sich vor, Sie hätten 20 Variablen ('v1' bis' v20'). Könnten Sie 'mutate' verwenden, ohne 10 Zeilen Code zu schreiben? – sbac

+0

Überprüfen Sie diese https://stackoverflow.com/a/34377242/6142664 – Facottons

+1

@Facottons - danke für den Sack. Ich habe die obige Antwort bearbeitet, um den von Ihnen vorgeschlagenen sauberen Ansatz zu berücksichtigen. –

1

Nur mutieren verwenden, wie mit einem Komma ist neue Spalten zu trennen mutate(df,"v1v3"=v1*v3,"v2v4"= v2*v4)

+0

Bitte beachten Sie meinen Kommentar oben. – sbac

1

Wir base R verwenden können anstelle der Verwendung keine zusätzlichen Pakete wie dplyr oder data.table

Wir können mapply verwenden, um die Operation für mehrere Vektoren gleichzeitig zu vektorisieren

mapply(function(x, y) df[x] * df[y], 
        paste0("v", 1:(ncol(df)/2)), paste0("v", (ncol(df)/2 + 1):ncol(df))) 

#$v1.v1 
#[1] 7 20 

#$v2.v2 
#[1] 20 18 

Wickeln Sie diese um data.frame, um einen Datenrahmen als Ausgabe zu erhalten.

data.frame(mapply(function(x, y) df[x] * df[y], 
        paste0("v", 1:(ncol(df)/2)), paste0("v", (ncol(df)/2 + 1):ncol(df)))) 

# v1.v1 v2.v2 
#1  7 20 
#2 20 18 

Wir verschmelzen können (cbind) dieser Datenrahmen zu Ihrem ursprünglichen dann.

+0

Ja, aber ich hatte ein besonderes Interesse daran, eine "dplyr" -Lösung zu betrachten. – sbac

+0

Gibt es einen bestimmten Grund, warum Sie nach einer "dplyr" -Lösung suchen? Ich bin nicht sehr vertraut damit. Vielleicht können wir warten, jemand würde es beantworten. –

+0

Ja, ich versuche das "ordentliches" Meta-Paket zu lernen. – sbac

2

Ich glaube, ich eine Lösung gefunden:

df %>% 
    mutate(n = df[1:(ncol(df)/2)] * df[(1+ncol(df)/2):(ncol(df))]) %>% head() 

Das Ergebnis ist gültig für eine beliebige Anzahl von Variablen. Es bleibt nur ein Problem mit dem Namen der neuen Variablen. Dies ist das Ergebnis:

v1 v2 v3 v4 n.v1 n.v2 
1 1 5 7 4 7 20 
2 2 6 10 3 20 18 
Verwandte Themen