代码之家  ›  专栏  ›  技术社区  ›  Gulbas

循环以跨列乘法

  •  2
  • Gulbas  · 技术社区  · 7 年前

    我有一个标有列的数据框 sales1 , sales2 , price1 , price2 我想通过乘以 销售1 * 价格1 以此类推,以迭代的方式跨越每个数字。

    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)
        }
      )
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   Ronak Shah    7 年前

    假设您的列已经排序( sales1 , sales2 , price1 , price2 ). 我们可以将数据帧分成两部分,然后将它们相乘

    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
  •  1
  •   markdly    7 年前

    这个答案并不简单。为此,@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