【问题标题】:In grouped data, how to arrange the rows of only *some* columns by the values of a column, while keeping the rest of columns untouched?在分组数据中,如何仅按列的值排列 *some* 列的行,同时保持其余列不变?
【发布时间】:2020-11-21 20:56:37
【问题描述】:

我有长格式的数据,按一个变量分组。我正在尝试按某个列中值的顺序按组对行进行排序/排列。问题是,我想对 some 列中的行应用这种排序,而其他列应该保持不变。我尝试使用mutate(across(...)) 对感兴趣的列进行操作,但出现错误。

示例数据

set.seed(2020)

df <-
  data.frame(name = rep(c("john", "bob", "ralph"), each = 8),
           test_scores = sample(30:100, size = 24),
           year_taken = sample(1993:2020, size = 24),
           dont_touch_this_col = LETTERS[1:24])

> df
##     name test_scores year_taken dont_touch_this_col
## 1   john          74       2002                   A
## 2   john          72       1993                   B
## 3   john          98       2007                   C
## 4   john          87       2014                   D
## 5   john          95       2001                   E
## 6   john          54       2008                   F
## 7   john          64       1998                   G
## 8   john          53       2020                   H
## 9    bob          79       2019                   I
## 10   bob          62       2012                   J
## 11   bob          83       2009                   K
## 12   bob          36       2000                   L
## 13   bob          37       2018                   M
## 14   bob          50       2004                   N
## 15   bob          85       2013                   O
## 16   bob          42       1994                   P
## 17 ralph          63       1997                   Q
## 18 ralph          34       2010                   R
## 19 ralph          33       1996                   S
## 20 ralph          48       2006                   T
## 21 ralph          77       2016                   U
## 22 ralph          52       2017                   V
## 23 ralph          82       2015                   W
## 24 ralph          47       2003                   X

name 分组并按year_taken 排列很容易

library(dplyr)

df %>%
  group_by(name) %>%
  arrange(year_taken, .by_group = TRUE)


## # A tibble: 24 x 4
## # Groups:   name [3]
##    name  test_scores year_taken dont_touch_this_col
##    <chr>       <int>      <int> <chr>              
##  1 bob            42       1994 P                  
##  2 bob            36       2000 L                  
##  3 bob            50       2004 N                  
##  4 bob            83       2009 K                  
##  5 bob            62       2012 J                  
##  6 bob            85       2013 O                  
##  7 bob            37       2018 M                  
##  8 bob            79       2019 I                  
##  9 john           72       1993 B                  
## 10 john           64       1998 G  

但我想在保持dont_touch_this_col 不变的情况下按组进行安排

一次失败的尝试是使用mutate(across()) 指定(或排除)特定变量:

df %>%
  group_by(name) %>%
  mutate(across(-dont_touch_this_col, arrange, year_taken, .by_group = TRUE))

错误:mutate() 输入 ..1 有问题。 x 没有适用的方法 'arrange_' 应用于类“c('integer', 'numeric')”的对象 i 输入..1across(-dont_touch_this_col, arrange, year_taken, .by_group = TRUE)。 i 组 1 中发生错误:name = "bob"。

那么我怎样才能按感兴趣的列(这里是year_taken)排列分组数据,同时保持一列(或多列)不参与操作?

【问题讨论】:

  • 也许你真的想使用sortarrange 函数将.data 作为其第一个参数,或者换句话说,它不像sort 那样排列数字/值的向量,而是对数据帧进行操作。此外,在(正确地)使用时,arrange 不会破坏行依赖关系。换句话说,如果您重新排列一列的行的顺序,您必须将所有其他列的行都沿用。对于arrange,您对整个数据框进行排序,但基于提供给arrange 的第二个参数的列中值的等级/顺序。

标签: r sorting dplyr


【解决方案1】:

也许试试这个。您可以使用bind_cols() 添加您希望保持不变的变量并将它们从排序任务中排除。代码如下:

library(dplyr)
set.seed(2020)
#Data
df <-
  data.frame(name = rep(c("john", "bob", "ralph"), each = 8),
             test_scores = sample(30:100, size = 24),
             year_taken = sample(1993:2020, size = 24),
             dont_touch_this_col = LETTERS[1:24])
#Code
newdf <- df %>% select(-dont_touch_this_col) %>%
  group_by(name) %>%
  arrange(year_taken, .by_group = TRUE) %>%
  bind_cols(df %>% select(dont_touch_this_col))

输出:

# A tibble: 24 x 4
# Groups:   name [3]
   name  test_scores year_taken dont_touch_this_col
   <fct>       <int>      <int> <fct>              
 1 bob            83       1998 A                  
 2 bob            79       2002 B                  
 3 bob            58       2003 C                  
 4 bob            63       2005 D                  
 5 bob            85       2013 E                  
 6 bob            45       2018 F                  
 7 bob            37       2019 G                  
 8 bob            95       2020 H                  
 9 john           65       1999 I                  
10 john           57       2004 J                  
# ... with 14 more rows

【讨论】:

    【解决方案2】:

    使用base R

    cbind(df[with(df, order(name, year_taken)), 
         c('name', 'test_scores', 'year_taken')], df['dont_touch_this_col'])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-15
      • 2021-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多