【问题标题】:Mutating multiple columns in a data frame using dplyr使用 dplyr 改变数据框中的多列
【发布时间】:2016-11-09 16:03:00
【问题描述】:

我有以下数据框df

  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)

【问题讨论】:

  • df %&gt;% mutate(v1v3=v1*v3) %&gt;% mutate(v2v4=v2*v4)
  • 我编辑了我的问题。我需要一个可以推广到任意数量的变量而不用全部写出来的答案。
  • 所以你想将交替列中的值相乘?
  • 好吧,现在:这是一个不同的问题 :-D 您实际上是在要求某人现在为您编写一个循环来生成您的 dplyr 代码。最好将 df1 乘以 df2:从比喻的角度来说,这确实是一个完全不同的蜡球。
  • 完全正确,但这不是用 tidyverse 写的... ;-) 当您提出一个问题然后更改它时,它会使下面第一个问题的所有答案都是“错误的”。您最好只选择一个回答了您的问题的回复,然后在新线程中提出您的新问题。你的解决方案很好,但不如你问其他人如何从一开始就解决这个特定问题时得到的一些东西好。然后,您将获得新的很酷的方法来做您不知道的事情 - 例如点积和数据帧到数据帧的乘法。

标签: r dplyr


【解决方案1】:

你真的很亲密。

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

这么漂亮简单的语言,对吧?

更多精彩技巧请见here.

编辑: 感谢@Facottons 指向此答案的指针:https://stackoverflow.com/a/34377242/5088194,这是解决此问题的 tidy 方法。它使人们不必在所需的每个新列中编写一行硬代码。虽然它比 Base R 方法更冗长,但逻辑至少更直接透明/可读。还值得注意的是,要使这种方法起作用,行数必须至少是列数的一半。

# 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)

【讨论】:

  • 现在假设您有 20 个变量(v1v20)。不用写 10 行代码就可以使用mutate吗?
  • @Facottons - 感谢您的戳。我已经编辑了上面的答案,以包含您建议的整洁方法。
【解决方案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

【讨论】:

  • 我不确定这对你有什么作用。它返回一个错误Error: Column `n` is of unsupported class data.frame
【解决方案3】:

我们可以使用base R 而不是使用任何额外的包,例如dplyrdata.table

我们可以使用mapply同时对多个向量进行向量化操作

n <- ncol(df)/2
mapply(`*`, df[1:n], df[(n + 1):ncol(df)])

#     v1 v2
#[1,]  7 20
#[2,] 20 18

然后我们可以将此数据框合并 (cbind) 到您的原始数据框。


如果您对tidyverse 解决方案感兴趣,purrr 中的等价物将是map2 的变体

purrr::map2_df(df[1:n], df[(n + 1):ncol(df)], `*`)

# A tibble: 2 x 2
#     v1    v2
#  <dbl> <dbl>
#1     7    20
#2    20    18

【讨论】:

  • 是的,但我对查看dplyr 解决方案特别感兴趣。
  • 您寻找dplyr 解决方案是否有特定原因?我对它不是很熟悉。也许我们可以等待,有人会回答。
【解决方案4】:

只需按原样使用 mutate 和逗号来分隔新列 mutate(df,"v1v3"=v1*v3,"v2v4"= v2*v4)

【讨论】:

  • 请看我上面的评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
  • 2015-02-24
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多