【问题标题】:Dividing a dataframe row wise using a vector with condition in r使用条件为 r 的向量逐行划分数据帧
【发布时间】:2022-12-10 08:50:25
【问题描述】:

我有一个数据框和一个向量,我想用它来划分数据框的每一行。

    col1 <- c(500, 20000, 50000)
    col2 <- c(20000, 500, 50000)
    col3 <- c(20000, 50000, 500)
    dividing_factor <- c(1.5, 2, 0.5)
    df <- data.frame(col1,col2, col3)
> df
   col1  col2  col3
1   500 20000 20000
2 20000   500 50000
3 50000 50000   500

我希望的结果看起来像下面的 df_div。本质上,只有大于 500 的值才应该用 dividing_factor 除。

    col1_div <- c(500, 20000/1.5, 50000/1.5)
    col2_div <- c(20000/2, 500, 50000/2)
    col3_div <- c(20000/0.5, 50000/0.5, 500)
    df_div <- data.frame(col1_div,col2_div,col3_div)

  col1_div col2_div col3_div
1   500.00    10000    4e+04
2 13333.33      500    1e+05
3 33333.33    25000    5e+02

我一直在使用如下的应用函数(请注意,在我的数据上下文中,我只选择标题中包含“Col”的列,并将输出组合到原始数据框。),但我可以不知道如何为其添加条件(仅除以 500 以上)。我试过将 mutate 与 ifelse 一起使用,但我用向量除法的事实给我的方法带来了麻烦。

df_div <- df %>%
  select(contains("Col")) %>%
  apply(., 1, function(x) {
      x / dividing_factor 
  }) %>%
  do.call(rbind, .) %>%
  as_tibble()

【问题讨论】:

    标签: r


    【解决方案1】:

    不需要使用apply,我们可以使用向量化/矩阵操作:

    df / t(ifelse(df > 500, dividing_factor, 1))
    #       col1  col2  col3
    # 1   500.00 10000 4e+04
    # 2 13333.33   500 1e+05
    # 3 33333.33 25000 5e+02
    

    【讨论】:

    • 非常感谢您提供这个简单的解决方案。我稍微改变了它以使其在我更大的数据框架中工作:df / t(ifelse(t(df) &gt; 500, dividing_factor, 1))。否则,dividing_factor 在垂直方向重复。如果其他人需要解决方案,请在此处添加注释。
    【解决方案2】:

    或者我们可以命名向量并使用 mutate/across:

    dividing_factor <- c("col1" = 1.5, "col2" = 2, "col3" = 0.5)
    
    df |>
      mutate(across(starts_with("col"),
                    ~ ifelse(. > 500, ./dividing_factor[cur_column()], .)))
    

    【讨论】:

      【解决方案3】:

      您可以获得所有值 > 500 的位置,并使用它来提取这些值并将其替换为您的计算结果。

      idx <- which(df != 500, arr.ind = TRUE)
      df[idx] <- (df / as.list(dividing_factor))[idx]
      

      这里的“技巧”是将df 除以列表。

      结果

      df
      #      col1  col2  col3
      #1   500.00 10000 4e+04
      #2 13333.33   500 1e+05
      #3 33333.33 25000 5e+02
      

      【讨论】:

        猜你喜欢
        • 2022-08-22
        • 2016-11-27
        • 2016-10-07
        • 1970-01-01
        • 1970-01-01
        • 2021-07-26
        • 1970-01-01
        • 2012-06-09
        • 2016-11-29
        相关资源
        最近更新 更多