使用dplyr汇总的可变结果,具体取决于输出变量命名

时间:2016-02-11 20:11:28

标签: r dplyr

我正在使用dplyr包(dplyr 0.4.3; R 3.2.3)来获取分组数据的基本摘要(summarise),但结果不一致(NaN for 'sd'和'N'的错误计数。)更改输出的“名称”具有可变效果(如下所示)。

到目前为止的结果摘要:

  • plyr包未加载,我知道如果首先加载,可能会导致dplyr出现问题。
  • 使用或不使用NA数据获得相同的结果(未示出)。
  • 可以通过使用camelCase变量命名(未显示)或使用名称中没有非字母数字分隔符的输出变量来解决问题。
  • 取决于“。”的组合,仍然可以获得有效结果。或输出列名称中的“_”。

问题:虽然可以解决这个问题,但是我是否违反了我违反的基本变量命名规则,或者是否存在需要解决的程序问题?我已经看到了带有变量行为的其他问题,但总结不多。

谢谢,马特

示例数据

library(dplyr)
df<-data_frame(id=c(1,1,1,2,2,2,3,3,3),
       time=rep(1:3, 3),
       glucose=c(90,150, 200,
                 100,150,200,
                 80,100,150))

示例:sd给出NaN且不准确n

df %>% group_by(time) %>%
  summarise(glucose=mean(glucose, na.rm=TRUE),
        glucose.sd=sd(glucose, na.rm=TRUE),
        n=sum(!is.na(glucose)))

   time  glucose glucose.sd     n
  (int)    (dbl)      (dbl) (int)
1     1  90.0000        NaN     1
2     2 133.3333        NaN     1
3     3 183.3333        NaN     1

我想知道使用“。”是否存在问题。在名字中, 或使用与数据框中相同的名称。从输出中删除现有的df col名称修复了此

df %>% group_by(time) %>%
  summarise(avg=mean(glucose, na.rm=TRUE),
        stdv=sd(glucose, na.rm=TRUE),
        n=sum(!is.na(glucose)))

   time      avg     stdv     n
  (int)    (dbl)    (dbl) (int)
1     1  90.0000 10.00000     3
2     2 133.3333 28.86751     3
3     3 183.3333 28.86751     3

即使留下“glucose.sd”,删除“葡萄糖”摘要也会修复它 示例:去除“葡萄糖”后,结果可以

df %>% group_by(time) %>%
  summarise(glucose.sd=sd(glucose, na.rm=TRUE),
        n=sum(!is.na(glucose)))

   time glucose.sd     n
  (int)      (dbl) (int)
1     1   10.00000     3
2     2   28.86751     3
3     3   28.86751     3

如果我添加“glucose.mean”作为第一个摘要,它可以正常工作

df %>% group_by(time) %>%
  summarise(glucose.mean=mean(glucose, na.rm=TRUE),
            glucose.sd=sd(glucose, na.rm=TRUE),
            n=sum(!is.na(glucose)))

   time glucose.mean glucose.sd     n
  (int)        (dbl)      (dbl) (int)
1     1      90.0000   10.00000     3
2     2     133.3333   28.86751     3
3     3     183.3333   28.86751     3

使用不带“。”的变量名时出现相同的错误。 所以这不仅仅是使用“。”的问题。名字

df %>% group_by(time) %>%
  summarise(glucose=mean(glucose, na.rm=TRUE),
        glucose_sd=sd(glucose, na.rm=TRUE),
        n=sum(!is.na(glucose)))

   time  glucose glucose_sd     n
  (int)    (dbl)      (dbl) (int)
1     1  90.0000        NaN     1
2     2 133.3333        NaN     1
3     3 183.3333        NaN     1

将“葡萄糖”重命名为“glucose_mean”有效

df %>% group_by(time) %>%
  summarise(glucose_mean=mean(glucose, na.rm=TRUE),
        glucose_sd=sd(glucose, na.rm=TRUE),
        n=sum(!is.na(glucose)))

   time glucose_mean glucose_sd     n
  (int)        (dbl)      (dbl) (int)
1     1      90.0000   10.00000     3
2     2     133.3333   28.86751     3
3     3     183.3333   28.86751     3

1 个答案:

答案 0 :(得分:3)

您在summarize中指定的转换按其出现的顺序执行,这意味着如果您更改变量值,则会为后续列显示这些新值(这与基函数{{1}不同})。当你这样做

tranform()

df %>% group_by(time) %>% summarise(glucose=mean(glucose, na.rm=TRUE), glucose.sd=sd(glucose, na.rm=TRUE), n=sum(!is.na(glucose))) 部分更改了glucose=mean(glucose, na.rm=TRUE)变量的值,以便在计算glucose部分时,glucose.sd=sd(glucose, na.rm=TRUE)看不到原始葡萄糖值,查看新值,即原始值的平均值。如果您重新排序列,它将起作用。

sd()

如果您想知道为什么这是默认行为,这是因为创建一个列然后在转换中使用该列值通常很好。例如,使用df %>% group_by(time) %>% summarise(glucose.sd=sd(glucose, na.rm=TRUE), n=sum(!is.na(glucose)), glucose=mean(glucose, na.rm=TRUE))

mutate()