子集与DF重复序列(subsetting df with repeated sequences)

2019-09-26 21:20发布

我已搜查高和低的解决方案,但我不能找到一个.....

我的数据框(基本上是没有的表1个的运动队按日期)拥有众多的场合一个或多个团队将在数据“重现”。 我想在退出每个周期的开始(或结束)日期没有。 1,每队。

的数据的一个例子可以是:

x1<- as.Date("2013-12-31")
adddate1 <- 1:length(teams1)
dates1 <- x1 + adddate1
teams2 <- c(rep("w", 3), rep("c", 8), rep("w", 4))
x2<- as.Date("2012-12-31")
adddate2 <- 1:length(teams2)
dates2 <- x2 + adddate2
dates <- c(dates2, dates1)
teams <- c(teams2, teams1)
df <- data.frame(dates, teams)
df$year <- year(df$dates)

这对于2013的样子:

        dates teams year
1  2013-01-01     w 2013
2  2013-01-02     w 2013
3  2013-01-03     w 2013
4  2013-01-04     c 2013
5  2013-01-05     c 2013
6  2013-01-06     c 2013
7  2013-01-07     c 2013
8  2013-01-08     c 2013
9  2013-01-09     c 2013
10 2013-01-10     c 2013
11 2013-01-11     c 2013
12 2013-01-12     w 2013
13 2013-01-13     w 2013
14 2013-01-14     w 2013
15 2013-01-15     w 2013

但是,使用ddply集合了相同名称的团队,并返回以下内容:

split <- ddply(df, .(year, teams), head,1)
split <- split[order(split[,1]),]

       dates teams year
2 2013-01-01     w 2013
1 2013-01-04     c 2013
3 2014-01-01     c 2014
4 2014-01-09     k 2014

有没有更优雅的方式来做到这一点不是创建它会去通过原DF和每个子集返回一个唯一值,将其添加到DF,然后使用ddply纳入新的独特的价值回归我想要什么功能?

Answer 1:

你说一些球队“重现”,并在这一点上我认为小intergroup的辅助函数, 这个答案可能就在这里的工具。 当你的情况,也有团队,例如“W”,在同年再次出现,如2013年,另一支球队已经存在了一段时间后,如“C”是非常有用的。 现在,如果你要正确对待每队作为单独的组occurence的每个序列,以获得该序列的第一个或最后日期,当这个功能非常有用。 需要注意的是,如果你只按“团队”和“年”,你通常会做,每个团队,如“W”只能(在dplyr使用“总结”时为例)有一个第一/最后日期。

定义函数:

intergroup <- function(var, start = 1) {
  cumsum(abs(c(start, diff(as.numeric(as.factor(var))))))
}

现在组数据首先由一年,然后还用在球队列组间的功能:

library(dplyr)
df %>%
  group_by(year) %>%
  group_by(teamindex = intergroup(teams), add = TRUE) %>%
  filter(dense_rank(dates) == 1)

最后,您可以根据自己的需要进行筛选。 这里有个例子,我筛选分钟日期。 其结果将是:

#Source: local data frame [3 x 4]
#Groups: year, teamindex
#
#       dates teams year teamindex
#1 2013-01-01     w 2013         1
#2 2013-01-04     c 2013         2
#3 2013-01-12     w 2013         3

需要注意的是团队的“W”再次出现,因为我们通过我们使用群体间的函数创建“teamindex”分组。

做过滤另一种选择是这样的(使用安排,然后slice ):

df %>%
  group_by(year) %>%
  group_by(teamindex = intergroup(teams), add = TRUE) %>%
  arrange(dates) %>%
  slice(1)

我使用的数据是从akrun的答案。



Answer 2:

你也可以使用rle创建teamindex

library(dplyr)
 df %>% 
    group_by(year) %>% 
    group_by(teamindex= with(rle(teams),
          rep(seq_along(lengths), lengths)), add=TRUE) %>%
          filter(dates==min(dates)) #or #filter(dates==max(dates))

 #        dates teams year teamindex
 #1 2013-01-01     w 2013         1
 #2 2013-01-04     c 2013         2
 #3 2013-01-12     w 2013         3

要么

df %>% 
   group_by(year) %>%
   group_by(teamindex= with(rle(teams),
      rep(seq_along(lengths), lengths)), add=TRUE) %>%
   arrange(dates) %>%
   slice(n()) #or #slice(1)
 #       dates teams year teamindex
 #1 2013-01-03     w 2013         1
 #2 2013-01-11     c 2013         2
 #3 2013-01-15     w 2013         3

数据

df <- structure(list(dates = structure(c(15706, 15707, 15708, 15709, 
15710, 15711, 15712, 15713, 15714, 15715, 15716, 15717, 15718, 
15719, 15720), class = "Date"), teams = c("w", "w", "w", "c", 
"c", "c", "c", "c", "c", "c", "c", "w", "w", "w", "w"), year = c(2013L, 
2013L, 2013L, 2013L, 2013L, 2013L, 2013L, 2013L, 2013L, 2013L, 
2013L, 2013L, 2013L, 2013L, 2013L)), .Names = c("dates", "teams", 
"year"), row.names = c("1", "2", "3", "4", "5", "6", "7", "8", 
"9", "10", "11", "12", "13", "14", "15"), class = "data.frame")


文章来源: subsetting df with repeated sequences
标签: r subset plyr