【问题标题】:Using R - reshape a dataframe based on group max values of another dataframe使用 R - 根据另一个数据帧的组最大值重塑数据帧
【发布时间】:2023-03-19 09:02:01
【问题描述】:

我正在处理一个非常大的数据集。请考虑以下示例:

df1<-{data.frame(MyID=c(1, 2, 3, 1, 2, 3, 1, 2, 3, 4, 5),v1=c(0.1, 0.2, NA, 0.4, 0.2, 0.1, 0.8, 0.3, 0.1, 0.4, 0.3), v2=c(NA, 0.4, 0.2, 0.1, 0.8, 0.3, 0.1, 0.4, 0.3, 0.1, 0.2))}

df2<-{data.frame(MyID=c(1, 2, 3, 1, 2, 3, 1, 2, 3, 4, 5),v1=c(10, 8, 0, 6, 10, 5, 3, 1, 10, 8, 3), v2=c(0, 10, 5, 1, 8, 5,10, 3, 3, 1, 5))}

我想从 df1 中提取信息,但基于 df2 中每个 MyID 的最大值。最终结果应该是一个数据框:

  • 每个唯一的 MyID 一行
  • 每一列的 df1 中的值对应于 df2 的 MyID 组的最大值。

结果应该是

ExpectedResult<-{data.frame(MyID=c(1, 2, 3, 4, 5),v1=c(0.1,0.2,0.1,0.4,0.3), v2=c(0.1,0.4,0.2,0.1,0.2))}

我已经尝试过但只解决了部分问题:

  • 使用组并找到每个组的最大值,例如df2Max&lt;- df2 %&gt;% group_by(MyID) %&gt;% slice_max(1,)
  • 使用例如分割数据df2.split &lt;- split(df2, list(df2$MyID))

但是,我仍然不确定如何链接两个数据框以提取我需要的内容。

【问题讨论】:

    标签: r dataframe group-by split max


    【解决方案1】:

    我们得到'v1','v2'的行索引,'df2'中值最高的列按'MyID'分组,然后通过'MyID'和summarise与第一个数据集进行连接@ 'v1', 'v2' 列基于'MyID'分组后的索引

    library(dplyr)
    df2 %>% 
       group_by(MyID) %>% 
       summarise(rnv1 = row_number()[which.max(v1)], 
                 rnv2 = row_number()[which.max(v2)], .groups = 'drop' ) %>%  
       right_join(df1, by = 'MyID') %>%
       group_by(MyID) %>% 
       summarise(v1 = v1[first(rnv1)], v2 = v2[first(rnv2)], .groups = 'drop')
    

    -输出

    # A tibble: 5 x 3
    #   MyID    v1    v2
    #  <dbl> <dbl> <dbl>
    #1     1   0.1   0.1
    #2     2   0.2   0.4
    #3     3   0.1   0.2
    #4     4   0.4   0.1
    #5     5   0.3   0.2
    

    或者另一种选择是加入data.table

    library(data.table)    
    nm1 <- names(df2)[-1]
    setDT(df1)[setDT(df2)[, lapply(.SD, which.max), MyID], 
        Map(function(x, y) x[first(y)], .SD, mget(paste0("i.", nm1))), 
        on = .(MyID), by = .EACHI]
    #   MyID  v1  v2
    #1:    1 0.1 0.1
    #2:    2 0.2 0.4
    #3:    3 0.1 0.2
    #4:    4 0.4 0.1
    #5:    5 0.3 0.2
    

    【讨论】:

    • 谢谢!问题是我有数千个这样的列 v1、v2、...vn。考虑到这一点,我们能否修改您的解决方案?
    • @ie-con 是的,那么更新后的 data.table 解决方案应该可以解决这个问题
    【解决方案2】:

    我们可以group_byMyID获取每列最大值的索引并存储在df3中。

    library(dplyr)
    
    df2 %>%
      group_by(MyID) %>%
      summarise(across(.fns = which.max)) -> df3
    

    我们将df3 按行拆分,将split df1MyID 拆分,并使用索引提取相关值。

    df3[-1] <- t(mapply(function(x, y) x[cbind(y, 1:ncol(x))], 
                split(df1[-1], df1$MyID), asplit(df3[-1], 1)))
    
    #   MyID    v1    v2
    #  <dbl> <dbl> <dbl>
    #1     1   0.1   0.1
    #2     2   0.2   0.4
    #3     3   0.1   0.2
    #4     4   0.4   0.1
    #5     5   0.3   0.2
    

    【讨论】:

    • 谢谢@Ronak Shah!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 2011-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多