2016-11-09 45 views
2

變異多列的數據幀我有以下的數據幀df使用dplyr

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

我想獲得以下數據幀df2乘以列V1 * V3和V2 * V4:

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

如何使用dplyr來做到這一點?使用mutate_each

我需要的解決方案可以是推廣到大量的變量而不僅僅是4(v1到v4)。 這是產生的例子代碼:

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%>%變異(v1v3 = V1 * V3)%>%變異(v2v4 = V2 * V4)' –

+0

我編輯我的問題。我需要一個可以推廣到任何數量變量的答案,而無需全部寫入。 – sbac

+0

所以你想要在不同的列中乘以數值? –

回答

8

你真的很接近。

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

這麼漂亮簡單的語言吧?

更偉大的技巧請參閱here.

編輯: 感謝@Facottons指針這樣的回答:https://stackoverflow.com/a/34377242/5088194,這裏是一個整潔方法來解決這個問題。它使人們不必在每一個新列所需的代碼中寫入一行代碼。雖然它比基於方法的更詳細一點,但邏輯至少更直接透明/可讀。同樣值得注意的是,至少有一半的行數與這種方法工作的列數相同。

# 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

現在想象你有20個變量('v1'到'v20')。你可以使用'mutate'而不寫10行代碼嗎? – sbac

+0

檢查此https://stackoverflow.com/a/34377242/6142664 – Facottons

+1

@Facottons - 感謝您的捅。我已經編輯了上面的答案,以包含您建議的整潔方法。 –

1

只需使用發生變異的是用逗號分隔的新列mutate(df,"v1v3"=v1*v3,"v2v4"= v2*v4)

+0

請看我上面的評論。 – sbac

1

我們可以用base R而不使用任何額外的包像dplyrdata.table

我們可以使用mapply向量化矢量化多個向量的操作

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 

將此包裹在data.frame左右以獲取數據幀作爲輸出。

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 

我們可以合併(cbind)這個數據幀到您原來的數據幀。

+0

是的,但我對查看'dplyr'解決方案感興趣。 – sbac

+0

您是否在尋找'dplyr'解決方案的具體原因?我對此不太瞭解。也許我們可以等待,有人會回答。 –

+0

是的,我正在學習'tidyverse'元包。 – sbac

2

我想我找到了解決辦法:

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

的成績有效期爲任意數量的變量。它只是新變量名稱的一個問題。這是結果:

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