【问题标题】:loop to multiply across columns循环以跨列相乘
【发布时间】:2017-11-02 03:23:25
【问题描述】:

我有一个数据框,其中包含标记为 sales1sales2price1price2 的列,我想通过在每个数字上乘以 sales1 * price1 等来计算收入迭代时尚。

data <- data_frame(
  "sales1" = c(1, 2, 3),
  "sales2" = c(2, 3, 4),
  "price1" = c(3, 2, 2),
  "price2" = c(3, 3, 5))

data
# A tibble: 3 x 4
#  sales1 sales2 price1 price2
#   <dbl>  <dbl>  <dbl>  <dbl>
#1      1      2      3      3
#2      2      3      2      3
#3      3      4      2      5

为什么下面的代码不起作用?

data %>%
  mutate (
    for (i in seq_along(1:2)) {
      paste0("revenue",i) = paste0("sales",i) * paste0("price",i)
    }
  )

【问题讨论】:

标签: r dataframe tidyverse dplyr


【解决方案1】:

假设您的列已排序(sales1sales2price1price2)。我们可以将数据帧分成两部分,然后将它们相乘

data[grep("sales", names(data))] * data[grep("price", names(data))]

#  sales1 sales2
#1      3      6
#2      4      9
#3      6     20

如果这些列还没有按照名称排序,我们可以使用order对它们进行排序,然后使用上面的命令。

data <- data[order(names(data))]

【讨论】:

    【解决方案2】:

    这个答案并不简短。为此,@RonakShah 现有的答案是值得一看的!

    我的回复旨在解决有关在tidyverse 中尝试执行此操作的困难的更广泛的担忧。我的理解是这很困难,因为数据目前不是“整洁”的格式。相反,您可以像这样创建一个整洁的数据框:

    library(tidyverse)
    
    tidy_df <- data %>% 
      rownames_to_column() %>%
      gather(key, value, -rowname) %>% 
      extract(key, c("variable", "id"), "([a-z]+)([0-9]+)") %>%
      spread(variable, value)
    

    这使得最终的计算变得简单

    tidy_df %>% mutate(revenue = sales * price)
    
    #> # A tibble: 6 x 5
    #>   rowname    id price sales revenue
    #>     <chr> <chr> <dbl> <dbl>   <dbl>
    #> 1       1     1     3     1       3
    #> 2       1     2     3     2       6
    #> 3       2     1     2     2       4
    #> 4       2     2     3     3       9
    #> 5       3     1     2     3       6
    #> 6       3     2     5     4      20
    

    如果您需要将数据恢复为原始格式,尽管我觉得这很笨拙(我相信这可以通过某种方式改进)。

    tidy_df %>% mutate(revenue = sales * price) %>%
      gather(key, value, -c(rowname, id)) %>%
      unite(key, key, id, sep = "") %>%
      spread(key, value) %>% 
      select(starts_with("price"), 
             starts_with("sales"),
             starts_with("revenue"))
    
    #> # A tibble: 3 x 6
    #>   price1 price2 sales1 sales2 revenue1 revenue2
    #> *  <dbl>  <dbl>  <dbl>  <dbl>    <dbl>    <dbl>
    #> 1      3      3      1      2        3        6
    #> 2      2      3      2      3        4        9
    #> 3      2      5      3      4        6       20
    

    【讨论】:

    • 我发现问题在于没有按照您描述的那样结构化数据。请参阅下面的另一个示例 df 以了解上下文 record &lt;- c(seq_along(1:10)) store &lt;- c(1, 2, 3, 4, 5, 1, 2, 3, 4, 5) week &lt;- c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2) sales_1 &lt;- c(3, 3, 3, 3, 3, 2, 5, 1, 2, 10) sales_2 &lt;- c(1, 2, 4, 5, 6, 2, 3, 6, 1, 8) price_1 &lt;- runif(10, 2, 6) price_2 &lt;- runif(10, 2, 6) df &lt;- data_frame(record, store, week, sales_1, sales_2, price_1, price_2) 我在使用稻草人代码压缩“销售”和“价格”列时遇到了困难。你能用这个例子指导我吗?
    • @Gulbas,这对我来说听起来像是一个新问题:)。如果您将其作为一个发布,我将尝试提供答案(您很可能会找到其他更好的解决方案)。您可以随时在新问题中链接回此问题,以便其他用户了解您正在寻找什么样的答案
    猜你喜欢
    • 2019-10-07
    • 2019-08-23
    • 1970-01-01
    • 2012-04-30
    • 2019-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多