如何避免在dplyr中的groupby列中安排

时间:2018-07-26 10:35:30

标签: r dplyr

我在R中有以下数据框

     Key       Quantity
     1_2013    20
     1_2013    20
     2_2013    20
     2_2013    30
     3_2013    20
     3_2013    20
     4_2013    20
     4_2013    30 
     10_2013   20
     10_2013   20
     11_2013   20
     11_2013   30

当我在Key列上进行汇总时,我想保持Key列的原始顺序。 但是,当我在dplyr中执行group_by时,它会给我以下顺序

     Key       Quantity
     1_2013    40
     10_2013   40
     11_2013   50
     2_2013    50
     3_2013    40
     4_2013    50

我要按照以下顺序

     Key       Quantity
     1_2013    40
     2_2013    50
     3_2013    40
     4_2013    50
     10_2013   40
     11_2013   50

我如何在dplyr中做到这一点?

3 个答案:

答案 0 :(得分:2)

OP请求当我在Key列上进行汇总时,我想保留Key列的原始顺序。

forcats :: fct_inorder()

属于forcats的{​​{1}}程序包具有tidyverse,它创建了一个因子,其中因子水平按出现顺序编号:

fct_inorder()
library(tidyverse)
read_table(
"    Key       Quantity
     1_2013    20
     1_2013    20
     2_2013    20
     2_2013    30
     3_2013    20
     3_2013    20
     4_2013    20
     4_2013    30 
     10_2013   20
     10_2013   20
     11_2013   20
     11_2013   30"
) %>% 
  group_by(Key = fct_inorder(Key)) %>% 
  summarise(Quantity = sum(Quantity))

# A tibble: 6 x 2 Key Quantity <fct> <int> 1 1_2013 40 2 2_2013 50 3 3_2013 40 4 4_2013 50 5 10_2013 40 6 11_2013 50

出于完整性考虑:
尽管OP明确要求提供data.table解决方案,但我只想提及在dplyr中与by =进行分组时,默认情况下会按出现顺序返回分组。因此,不需要任何因素。

data.table
library(data.table)
fread(
  "    Key       Quantity
     1_2013    20
     1_2013    20
     2_2013    20
     2_2013    30
     3_2013    20
     3_2013    20
     4_2013    20
     4_2013    30 
     10_2013   20
     10_2013   20
     11_2013   20
     11_2013   30"
)[, .(Quantity = sum(Quantity)), by = Key]

答案 1 :(得分:1)

一种可能的方法是按照您喜欢的顺序(即出现在原始数据集中)将分组变量转换为因子变量:

df = read.table(text = "
Key       Quantity
1_2013    20
1_2013    20
2_2013    20
2_2013    30
3_2013    20
3_2013    20
4_2013    20
4_2013    30 
10_2013   20
10_2013   20
11_2013   20
11_2013   30
", header=T, stringsAsFactors=F)

library(dplyr)

df %>%
  group_by(Key = factor(Key, levels = unique(Key))) %>%
  summarise(Quantity = sum(Quantity))

# # A tibble: 6 x 2
#    Key     Quantity
#    <fct>      <int>
# 1 1_2013        40
# 2 2_2013        50
# 3 3_2013        40
# 4 4_2013        50
# 5 10_2013       40
# 6 11_2013       50

如果需要,可以通过在最后添加... %>% mutate(Key = as.character(Key))来变回字符变量。

答案 2 :(得分:1)

您已经堕落为字符排序祈祷。您将按照我个人(高度主观)的偏好提供一些选项。

df <- "Key,Quantity
1_2013,20
1_2013,20
2_2013,20
2_2013,30
3_2013,20
3_2013,20
4_2013,20
4_2013,30 
10_2013,20
10_2013,20
11_2013,20
11_2013,30"

df <- read.csv(text = df, stringsAsFactors = FALSE)

标准化字符长度

在整个向量中保持字符长度一致的优点是,它消除了很多排序问题。

df %>% 
  mutate(Key = sub("^(\\d{1})_", "0\\1_", Key)) %>% 
  group_by(Key) %>% 
  summarise(Quantity = sum(Quantity))

使Key成为一个因素

原则上Key是一个因子变量。如果不再需要对其进行任何操作,则没有理由将其保留为字符值。

library(dplyr)
library(gtools)
df %>% 
  mutate(Key = factor(Key,
                      labels = mixedsort(unique(Key)))) %>% 
  group_by(Key) %>% 
  summarise(Quantity = sum(Quantity))

采用老式的排序方式

使用mixedsort并按索引排序。

library(dplyr)
library(gtools)
df <- 
  df %>% 
  group_by(Key) %>% 
  summarise(Quantity = sum(Quantity))
df <- df[mixedorder(df$Key), ]