我正在努力处理来自R中的data.frame的数据请求,其中包含一个包含俱乐部的表,他们的ID,他们成立的年份,他们所属的地区的ID以及他们去过的年份关闭。 data.frame dat
看起来像
club_id founded district_id closed
1 2012 1 NA
2 2012 2 2014
3 2013 2 NA
4 2013 3 2014
...
NA
列中的 closed
表示该俱乐部仍然存在于当前年份(2016年)。
我想要的是每年仍然存在的俱乐部的数量,例如,这将为我提供上面的数据片段:
2012 2013 2014 ...
2 4 2 ...
我尝试使用dplyr
dat %>%
group_by(founded) %>%
summarise(clubs_per_year = n_distinct(club_id))
但是,这只给了我每年新成立的俱乐部数量,而不是每年现有俱乐部的总数。
答案 0 :(得分:2)
我不确定如何使用dplyr
实现此目的,但这是一个可能的data.table
解决方案。这基本上是为每个俱乐部创建一个序列,同时用当前年份替换NA
,然后计算每年的事件数
library(data.table)
setDT(df)[, .(Year = founded:(replace(closed, is.na(closed), year(Sys.Date())) - 1L)),
by = club_id
][, .(Uniques = uniqueN(club_id)), by = Year]
# Year Uniques
# 1: 2012 2
# 2: 2013 4
# 3: 2014 2
# 4: 2015 2
答案 1 :(得分:1)
我尝试了一个完整的解决方案。攻击计划是为每个俱乐部生成一系列活跃的年份,然后计算每个活跃年份的俱乐部ID。
首先,我们计算出每个俱乐部的最后一个活跃年份。
max_year <- 2015
years <- data_frame(
club_id = 1:4,
founded = c(2012, 2012, 2013, 2013),
closed = c(NA, 2014, NA, 2014))
years <- years %>%
mutate(last_active = ifelse(is.na(closed), max_year, closed - 1))
years
#> Source: local data frame [4 x 4]
#>
#> club_id founded closed last_active
#> (int) (dbl) (dbl) (dbl)
#> 1 1 2012 NA 2015
#> 2 2 2012 2014 2013
#> 3 3 2013 NA 2015
#> 4 4 2013 2014 2013
接下来,我们创建另一个数据框,其中包含数据中每个founded
- last_active
范围内每个活动年份的一行。我们使用do
函数执行此操作。 do
让我们计算数据帧上的任意函数;唯一的规则是函数需要返回一个数据框。 do
尊重分组变量,因此也会返回分组列。
# Create a single-column data-frame with a sequence of values
seq_df <- function(col_name, min, max) {
data.frame(seq(min, max)) %>% setNames(col_name)
}
year_scheme <- years %>%
# Find each found-last_active pairings
select(founded, last_active) %>%
distinct %>%
# Create a sequence of rows for each of those pairings
group_by(founded, last_active) %>%
do(seq_df("active_year", .$founded, .$last_active)) %>%
ungroup
year_scheme
#> Source: local data frame [10 x 3]
#>
#> founded last_active active_year
#> (dbl) (dbl) (int)
#> 1 2012 2013 2012
#> 2 2012 2013 2013
#> 3 2012 2015 2012
#> 4 2012 2015 2013
#> 5 2012 2015 2014
#> 6 2012 2015 2015
#> 7 2013 2013 2013
#> 8 2013 2015 2013
#> 9 2013 2015 2014
#> 10 2013 2015 2015
最后,我们可以加入表并计算组ID。
full_years <- left_join(years, year_scheme)
#> Joining by: c("founded", "last_active")
full_years
#> Source: local data frame [10 x 5]
#>
#> club_id founded closed last_active active_year
#> (int) (dbl) (dbl) (dbl) (int)
#> 1 1 2012 NA 2015 2012
#> 2 1 2012 NA 2015 2013
#> 3 1 2012 NA 2015 2014
#> 4 1 2012 NA 2015 2015
#> 5 2 2012 2014 2014 2012
#> 6 2 2012 2014 2014 2013
#> 7 3 2013 NA 2015 2013
#> 8 3 2013 NA 2015 2014
#> 9 3 2013 NA 2015 2015
#> 10 4 2013 2014 2014 2013
# years per club
full_years %>% count(club_id)
#> Source: local data frame [4 x 2]
#>
#> club_id n
#> (int) (int)
#> 1 1 4
#> 2 2 2
#> 3 3 3
#> 4 4 1
# clubs per year
full_years %>% count(active_year)
#> Source: local data frame [4 x 2]
#>
#> active_year n
#> (int) (int)
#> 1 2012 2
#> 2 2013 4
#> 3 2014 2
#> 4 2015 2
答案 2 :(得分:0)
此解决方案使用dcast
包中的data.table
:
library(data.table)
##Example data
DT <- data.table(club_id=1:4, founded=rep(2012:2013, each=2),
district_id=c(1, 2, 2, 3), closed=rep(c(NA, 2014), 2))
## Fill in NAs with current year, create row for each year the club
## exists, cast to columns for each year, and get the count of clubs
## per year using length function
dcast(DT[, .(year=founded:ifelse(is.na(closed), year(Sys.Date()), closed)),
by=club_id], . ~ year, length, fill=0)
## . 2012 2013 2014 2015 2016
## 1: . 2 4 4 2 2
以下版本类似,但除非全年开放,否则不会计算一年内的俱乐部。请注意俱乐部在同一年开放和关闭的情况。我已经添加了一个在2015年开放和关闭的俱乐部。
DT2 <- data.table(club_id=1:5, founded=c(rep(2012:2013, each=2), 2015),
district_id=c(1, 2, 2, 3, 3),
closed=c(rep(c(NA, 2014), 2), 2015))
## Fill in missing values with the current year
DT2[, closed2:=ifelse(is.na(closed), year(Sys.Date()), closed)]
## Cast to columns as before, ignore cases where the club's open and
## closed years match, and then subtract one from the closed year
dcast(DT2[founded!=closed2, .(year=founded:(closed2-1)), by=club_id],
. ~ year, length, fill=0)
## . 2012 2013 2014 2015
## 1: . 2 4 2 2
答案 3 :(得分:0)
以下是具有不同方法的dplyr
解决方案
注意:我在几天前想出了这个,但我发现了n_distinct
的错误并报告了它;它现在已在最新的开发版本中修复。在dplyr
的旧版本中,我必须使用dplyr::n_distinct
,但当前版本只需要n_distinct
。
此方法会创建一个带有年份列的data.frame
,并根据dat
data.frame
(来自OP的数据)对其进行修改
library(dplyr)
yrdf <- data.frame(year = 2012:2015) # "dat" could be used to create this as well.
## For each year calculate the count based on the data in 'dat'
yrdf %>%
group_by(year) %>%
mutate(count = n_distinct(
dat$club_id[ (is.na(dat$closed) | (dat$closed > year)) & dat$founded <= year]
)
) %>%
ungroup
## year count
## (int) (int)
## 1 2012 2
## 2 2013 4
## 3 2014 2
## 4 2015 2