【问题标题】:Find row maximum across columns by using vector of column names in dplyr通过使用 dplyr 中的列名向量查找列中的最大行数
【发布时间】:2019-04-10 19:30:55
【问题描述】:

我在一个字符向量中有一长串列名,它们指代各种药物。我喜欢将该列表保留在我的代码顶部,以便在我的脚本中的各个点上轻松编辑和引用药物组。我想使用 dplyr 获取药物中的行最大值,方法是为其提供列名的预定义向量以找到最大值。似乎有一个简单的解决方法,但它今天让我失望了......

我尝试了下面的代码,但它返回列名列表中的名称之一。

我还尝试了使用 get()、select() 和 do.call() 的各种排列,以尝试让 R 以不同的方式读取字符向量,但我无法弄清楚...

data(mtcars)

colnames <- c("vs", "am", "gear", "carb")

df <- mtcars %>%
  rowwise() %>%
  mutate(max = max(colnames))

编辑:我希望在新列中显示最大值。例如,我希望输出如下:

vs am gear carb MAX
0  1   4    4    4
0  1   4    4    4
1  1   4    1    4
1  0   3    1    3
0  0   3    2    3

【问题讨论】:

  • 如果最大值出现平局怎么办?您可以与mtcars 分享您想要的输出吗? pmax 可能比 max 这里更好
  • @Mike 我在上面添加了一个我想要的输出示例。我确实认为 pmax 可能是正确的。
  • 我在下面更新了我的答案,还展示了一种使用pmax的方法

标签: r dplyr


【解决方案1】:

您还可以通过先将数据变长然后找到最大值并将其加入原始数据来整理数据。请注意,您必须在此处使用 gather_() 并将所有名称都放在引号中,以便您可以引用您的向量。在此示例中,我使用汽车作为您的药物,并且没有解决最大值是否存在平局。

library(dplyr)
library(tidyr)
colnames <- c("vs", "am", "gear", "carb")

df <- mtcars %>%
      mutate(nms = row.names(mtcars)) 
#transpose then find max value and keep max value
dfx <-  tidyr::gather_(df, 'nms2','vals', colnames) %>% 
        group_by(nms) %>% 
        mutate(max = max(vals)) %>% 
        ungroup %>% 
        filter(max == vals)
#join back on to data with column name and max value 
mt2 <- left_join(df,select(dfx, nms, vals,nms2),by='nms')

使用 pmax 和更少的代码

您可以在 do.call 内使用 pmax 到行最大值

df <- mtcars %>% 
      mutate(mx2 = do.call(pmax,mtcars[,colnames]))

【讨论】:

    【解决方案2】:

    这可能不是最dplyr 的答案,但您始终可以在mutate 中使用apply

    mtcars %>%
      mutate(max_val = apply(., 1, function(x) max(x[col_names]))) %>%
      head()
    
       mpg cyl disp  hp drat    wt  qsec vs am gear carb max_val2 max_val
    1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4        4       4
    2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4        4       4
    3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1        4       4
    4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1        3       3
    5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2        3       3
    6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1        3       3
    

    或者,你可以这样做:

    mtcars$max_val2 <- mtcars %>%
      select(col_names) %>%
      transmute(apply(., 1, max)) %>%
      pull()
    head(mtcars)
    
                       mpg cyl disp  hp drat    wt  qsec vs am gear carb max_val2
    Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4        4
    Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4        4
    Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1        4
    Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1        3
    Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2        3
    Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1        3
    

    【讨论】:

      【解决方案3】:

      在您最初的尝试中使用c_across 似乎有效:

      mycols <- c("vs", "am", "gear", "carb")
      
      df <- mtcars %>% 
        rowwise() %>%
        mutate(MAX = max(c_across(all_of(mycols)))) 
      

      【讨论】:

        【解决方案4】:

        您可以使用dplyr 中的summarise_at 汇总选定数量的列或列向量:

        data(mtcars)
        
        colnames <- c("vs", "am", "gear", "carb")
        
        df <- mtcars %>%
          summarise_at(colnames, list(max))
        
          vs am gear carb
        1  1  1    5    8
        

        您只需先指定列,然后再指定函数;在这种情况下maxselect_atmutate_atrename_at 的语法相同 - 您使用 summarise_at 是因为您保留指定的列而不是创建新列。

        【讨论】:

        • 这似乎不是按行的最大值。
        猜你喜欢
        • 2015-03-04
        • 1970-01-01
        • 2021-07-02
        • 1970-01-01
        • 2016-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-14
        相关资源
        最近更新 更多