我有一个大数据框,其中有一列,具有一个组名,该组名与 dplyr 分组。因此,多行具有相同的组名。为了减少数据,我想从每个组的第一个元素中提取第n个元素。有没有 R方式而没有循环?
用序列对每一行进行子集化,经常会丢失每个组的第一行。例如
<p>Somewhere!</p>
输入:
data[seq(1, nrow(data), 10), ] # Some groups start without the first row.
输出(第二个元素,请注意第三行!):
Val Group
1 1.0 Fruit
2 2.0 Fruit
3 3.0 Fruit
4 1.5 Veg
5 2.8 Veg
6 4.2 Veg
7 5.1 Veg
答案 0 :(得分:8)
library(dplyr)
data %>% group_by(Group) %>%
slice(seq(1, n(), by = 2))
这给出了:
# A tibble: 4 x 2
# Groups: Group [2]
Val Group
<dbl> <fct>
1 1 Fruit
2 3 Fruit
3 1.5 Veg
4 4.2 Veg
答案 1 :(得分:2)
这是基本的R方式:
DF$ID_by_Group <- ave(DF$Val, DF$Group, FUN = seq_along)
DF[DF$ID_by_Group %in% seq(1,3, by = 2), ]
Val Group ID_by_Group
1 1.0 Fruit 1
3 3.0 Fruit 3
4 1.5 Veg 1
6 4.2 Veg 3
ave()
函数按组创建一个ID。第二条语句只是基于我们创建的ID_by_Group
进行过滤。
请注意,我们可以一次完成所有操作和/或删除添加的列:
DF[ave(DF$Val, DF$Group, FUN = seq_along) %in% seq(1,3, by = 2), ]
DF$ID_by_Group <- ave(DF$Val, DF$Group, FUN = seq_along)
DF[DF$ID_by_Group %in% seq(1,3, by = 2), -3]
DF[DF$ID_by_Group %in% seq(1,3, by = 2), -grep('ID_by_Group', names(DF))]
DF[DF$ID_by_Group %in% seq(1,3, by = 2), c('Val', 'Group')]
#all provide:
Val Group
1 1.0 Fruit
3 3.0 Fruit
4 1.5 Veg
6 4.2 Veg
答案 2 :(得分:0)
另一种选择是data.table
:
> setDT(data)
> data[(rowid(Group) %% 2) == 1]
Val Group
1: 1.0 Fruit
2: 3.0 Fruit
3: 1.5 Veg
4: 4.2 Veg
答案 3 :(得分:0)
另一个基本R选项,可使用ave
展开回收属性来选择每组中的第n行
n <- 2
df[as.logical(with(df, ave(Val, Group, FUN = function(x)
c(TRUE, rep(FALSE, n - 1))))), ]
# Val Group
#1 1.0 Fruit
#3 3.0 Fruit
#4 1.5 Veg
#6 4.2 Veg
这将返回警告消息,因为返回的向量长度不同,但我认为可以忽略。
或者在评论中使用@thelatemail的想法,但不会给出警告消息。
df[as.logical(with(df, ave(Val, Group, FUN = function(x)
seq_along(x) %% 2 == 1))), ]