r - dplyr:保留因子的空级别,但不保留未出现在数据中的因子组合的空级别
问题描述
使用 进行分组和汇总时dplyr
,保留每个分组因子的空级别但不保留多个分组因子的空组合的正确方法是什么?
例如,考虑在多个站点的不同时间记录的数据。我可能会过滤然后计算每个站点中每年的某些内容。如果过滤器完全删除一年,我希望在空向量上使用摘要的默认值。所以站点“a”有 10 年,站点“b”有 1 年,所以我总是希望摘要中有 11 行。
如果我使用.drop = TRUE
我group_by
会失去几年:
library(dplyr)
library(zoo)
library(lubridate)
set.seed(1)
df <- data.frame(site = factor(c(rep("a", 120), rep("b", 12))),
date = c(seq.Date(as.Date("2000/1/1"), by = "month", length.out = 120), seq.Date(as.Date("2000/1/1"), by = "month", length.out = 12)),
value = rnorm(132, 50, 10))
df$year <- factor(lubridate::year(df$date))
df %>%
filter(value > 65) %>%
group_by(site, year, .drop = TRUE) %>%
summarise(f = first(date))
#> # A tibble: 6 x 3
#> # Groups: site [1]
#> site year f
#> <fct> <fct> <date>
#> 1 a 2000 2000-04-01
#> 2 a 2004 2004-08-01
#> 3 a 2005 2005-01-01
#> 4 a 2007 2007-11-01
#> 5 a 2008 2008-10-01
#> 6 a 2009 2009-02-01
并且.drop = FALSE
我为站点“b”获得了所有额外的年份,这些年不在原始数据中:
df %>%
filter(value > 65) %>%
group_by(site, year, .drop = FALSE) %>%
summarise(f = first(date))
#> # A tibble: 20 x 3
#> # Groups: site [2]
#> site year f
#> <fct> <fct> <date>
#> 1 a 2000 2000-04-01
#> 2 a 2001 NA
#> 3 a 2002 NA
#> 4 a 2003 NA
#> 5 a 2004 2004-08-01
#> 6 a 2005 2005-01-01
#> 7 a 2006 NA
#> 8 a 2007 2007-11-01
#> 9 a 2008 2008-10-01
#> 10 a 2009 2009-02-01
#> 11 b 2000 NA
#> 12 b 2001 NA
#> 13 b 2002 NA
#> 14 b 2003 NA
#> 15 b 2004 NA
#> 16 b 2005 NA
#> 17 b 2006 NA
#> 18 b 2007 NA
#> 19 b 2008 NA
#> 20 b 2009 NA
我能想到的最好方法是计算计数,然后合并然后过滤,然后删除计数变量,但这很混乱。我知道.drop
最近才添加到dplyr
,这对于一个因素非常有用,但是还有一种干净的方法可以为多个因素做到这一点吗?
df %>%
filter(value > 65) %>%
group_by(site, year, .drop = FALSE) %>%
summarise(f = first(date)) %>%
left_join(df %>% count(site, year, .drop = FALSE), by = c("site", "year")) %>%
filter(n > 0) %>%
select(-n)
#> # A tibble: 11 x 3
#> # Groups: site [2]
#> site year f
#> <fct> <fct> <date>
#> 1 a 2000 2000-04-01
#> 2 a 2001 NA
#> 3 a 2002 NA
#> 4 a 2003 NA
#> 5 a 2004 2004-08-01
#> 6 a 2005 2005-01-01
#> 7 a 2006 NA
#> 8 a 2007 2007-11-01
#> 9 a 2008 2008-10-01
#> 10 a 2009 2009-02-01
#> 11 b 2000 NA
解决方案
不确定这是不是你喜欢的。
如果您将日期替换value < 65
为 NA 而不是将其过滤掉,您可以照常进行。
df %>%
mutate(date = replace(date, value < 65, NA)) %>%
group_by(site, year) %>%
summarise(f = first(date[!is.na(date)]))
# A tibble: 11 x 3
# Groups: site [2]
site year f
<fct> <fct> <date>
1 a 2000 NA
2 a 2001 NA
3 a 2002 2002-03-01
4 a 2003 NA
5 a 2004 NA
6 a 2005 NA
7 a 2006 2006-02-01
8 a 2007 NA
9 a 2008 2008-07-01
10 a 2009 2009-02-01
11 b 2000 2000-08-01
推荐阅读
- mysql - Mysql 中的 JSON 和 Unicode Hex
- angular - 谷歌地图 javascript infoWindow 为空
- javascript - 对于 WordPress 元素编辑器 frontend.min.js 和 jquery.min.js 冲突
- android - 如何同步第二个屏幕并使其可点击?
- azure-virtual-machine - 同一虚拟网络中的 Azure 堡垒和专用链接:通过堡垒访问虚拟机失败
- c++ - 仅查找二叉树中最深叶节点的总和?
- python - 为什么会出现 (A) 这样的状态?
- python - 不使用包仍然出现错误:不能在 . 已经有由包管理的奴隶
- python - Selenium 使用 get_attributes 方法制作列表
- java - 如何计算用户输入的数字