【问题标题】:Order values within column according to values within different column by group in R根据R中不同列内的值对列内的值进行排序
【发布时间】:2019-07-20 09:34:44
【问题描述】:

我有以下面板数据集:

group  i  f  r  d
1      4  8  3  3
1      9  4  5  1
1      2  2  2  2
2      5  5  3  2
2      3  9  3  3
2      9  1  3  1

我想根据每个组的 d 列中的值重新排序此数据框中的第 i 列。因此,第 i 列中第 1 组的最大值应对应于 d 列中的最大值。最后我的 data.frame 应该是这样的:

group  i  f  r  d
1      9  8  3  3
1      2  4  5  1
1      4  2  2  2
2      5  5  3  2
2      9  9  3  3
2      3  1  3  1

【问题讨论】:

    标签: r sorting panel


    【解决方案1】:

    这是dplyr 解决方案。

    首先,按group 分组。然后在一个临时的新列ord中获取列d的排列重排,并使用它对i重新排序。

    library(dplyr)
    
    df1 %>%
      group_by(group) %>%
      mutate(ord = order(d),
             i = i[ord]) %>%
      ungroup() %>%
      select(-ord)
    ## A tibble: 6 x 5
    #  group     i     f     r     d
    #  <int> <int> <int> <int> <int>
    #1     1     9     8     3     3
    #2     1     2     4     5     1
    #3     1     4     2     2     2
    #4     2     9     5     3     2
    #5     2     5     9     3     3
    #6     2     3     1     3     1
    

    【讨论】:

    • 谢谢,我接受了另一个答案,因为它更短,但我应用了你的代码。
    • @JjBlevins 如果您仔细观察,此答案不会提供您想要的输出。诚然,我的第一次尝试也没有 - 请参阅我的编辑。
    【解决方案2】:

    原始(错误)

    您可以使用dplyrrank 实现此目的:

    library(dplyr)
    
    df1 %>% group_by(group) %>%
      mutate(i = i[rev(rank(d))])
    

    编辑

    这个问题实际上比最初看起来更棘手,而且我发布的原始答案不正确。正确的解决方案按i 排序,然后按d 的等级进行子集化。这提供了 OP 所需的输出,而我之前的回答没有(不注意!)

    df1 %>% group_by(group) %>%
      mutate(i = i[order(i)][rank(d)])
    
    # A tibble: 6 x 5
    # Groups:   group [2]
    #  group     i     f     r     d
    #  <int> <int> <int> <int> <int>
    #1     1     9     8     3     3
    #2     1     2     4     5     1
    #3     1     4     2     2     2
    #4     2     5     5     3     2
    #5     2     9     9     3     3
    #6     2     3     1     3     1
    

    【讨论】:

      【解决方案3】:

      data.table 的选项

      library(data.table)
      setDT(df1)[, i := i[order(d)], group]
      df1
      #   group i f r d
      #1:     1 9 8 3 3
      #2:     1 2 4 5 1
      #3:     1 4 2 2 2
      #4:     2 9 5 3 2
      #5:     2 5 9 3 3
      #6:     2 3 1 3 1
      

      如果我们需要第二个版本

      setDT(df1)[, i := sort(i)[d], group]
      

      数据

      df1 <- structure(list(group = c(1L, 1L, 1L, 2L, 2L, 2L), i = c(4L, 9L, 
      2L, 5L, 3L, 9L), f = c(8L, 4L, 2L, 5L, 9L, 1L), r = c(3L, 5L, 
      2L, 3L, 3L, 3L), d = c(3L, 1L, 2L, 2L, 3L, 1L)), class = "data.frame",
      row.names = c(NA, 
      -6L))
      

      【讨论】:

      • 这与 OP 的预期输出不匹配
      • @Chris 我在一些答案中找到了两个版本。所以,我正在使用其中一个版本
      • 是的,但是根据 OP 的描述,只有一个版本给出了正确的答案。不确定两个版本来自哪里
      • @Chris 在 OP 的预期中是9 2 4 5 9 3
      • 是的,我同意因此我的第一条评论。
      【解决方案4】:

      关于预期的输出有些混乱。在这里,我展示了一种获取两种输出版本的方法。

      使用splitmapply 的基本R

      df$i <- c(mapply(function(x, y) sort(y)[x], 
                        split(df$d, df$group), split(df$i, df$group)))
      
      df
      #  group i f r d
      #1     1 9 8 3 3
      #2     1 2 4 5 1
      #3     1 4 2 2 2
      #4     2 5 5 3 2
      #5     2 9 9 3 3
      #6     2 3 1 3 1
      

      或其他版本

      df$i <- c(mapply(function(x, y) y[order(x)], 
                       split(df$d, df$group), split(df$i, df$group)))
      
      df
      #  group i f r d
      #1     1 9 8 3 3
      #2     1 2 4 5 1
      #3     1 4 2 2 2
      #4     2 9 5 3 2
      #5     2 5 9 3 3
      #6     2 3 1 3 1
      

      我们也可以使用dplyr

      对于第一个版本

      library(dplyr)
      df %>%
        group_by(group) %>%
        mutate(i = sort(i)[d])
      

      @Rui 已经使用order 显示了第二个版本

      df %>%
        group_by(group) %>%
        mutate(i = i[order(d)])
      

      【讨论】:

      • 您的第一个版本假定 d 中的值是连续的(如果 d 中的一个值更改为 4,它将中断),因此我在解决方案中使用了 rank(d)。没错,正如我写的那样,sort(i)i[order(i)]
      猜你喜欢
      • 1970-01-01
      • 2018-10-12
      • 2017-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-05
      • 2021-08-19
      • 2019-04-15
      相关资源
      最近更新 更多