R 选择组中的第二个元素

use*_*147 3 select r

我试图找到一种更 R 风格的方式来选择 R 中组的第二个元素(但不是第一个)。

我结束了: 1. 创建一个索引rowNumIndex;2. 选择并将前行放入一个数据框中,然后将前行放入单独的数据框中;然后 3. “反向合并” 2 个数据帧以仅从数据帧中获取前两行的唯一值:

firsts <- ddply(df,.(group), function(x) head(x,1)) # 2 records using data below

seconds <- ddply(df,.(group), function(x) head(x,2)) # 4 records using data below

real.seconds <- seconds[!seconds$rowNumIndex %in% firsts$rowNumIndex, ] # 2 records, the second elements only
Run Code Online (Sandbox Code Playgroud)

这是一些假装数据:

group     var1     rowNumIndex
A         8        1
A         9        2
A         10       3
B         11       4
B         12       5
B         13       6
B         14       7


structure(list(group = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 2L
), .Label = c("A", "B"), class = "factor"), var1 = 8:14, rowNumIndex = 1:7), .Names = c("group", 
"var1", "rowNumIndex"), class = "data.frame", row.names = c(NA, 
-7L))
Run Code Online (Sandbox Code Playgroud)

所以,数据框firsts看起来像:

group     var1     rowNumIndex
A         8        1
B         11       4
Run Code Online (Sandbox Code Playgroud)

和数据框seconds看起来像:

group     var1     rowNumIndex
A         8        1
A         9        2
B         11       4
B         12       5
Run Code Online (Sandbox Code Playgroud)

和数据框real.seconds看起来像:

group     var1     rowNumIndex
A         9        2
B         12       5
Run Code Online (Sandbox Code Playgroud)

有没有办法在不求助于索引的情况下做到这一点?提前感谢您提供的无疑是一个令人心碎的简单而优雅的解决方案!

Car*_*lli 6

一个解决方案dplyr

library(dplyr)

group_by(df, group) %>% slice(2)

#     group  var1 rowNumIndex
#    <fctr> <int>       <int>
# 1      A     9           2
# 2      B    12           5
Run Code Online (Sandbox Code Playgroud)

dplyr 0.3替代:

group_by(df, group)%.%filter(seq_along(var1)==2)
  group var1 rowNumIndex
1     A    9           2
2     B   12           5
Run Code Online (Sandbox Code Playgroud)

此解决方案将保留数据的所有列。如果你只想要两列(group 和 var),你可以这样做:

group_by(df, group)%.%summarise(var1[2])
  group var1[2]
1     A       9
2     B      12
Run Code Online (Sandbox Code Playgroud)

一个解决方案splitlapplydo.call

real.seconds<-do.call("rbind", lapply(split(df, df$group), function(x) x[2,]))
Run Code Online (Sandbox Code Playgroud)

这会给你:

real.seconds
  group var1 rowNumIndex
A     A    9           2
B     B   12           5
Run Code Online (Sandbox Code Playgroud)

或者,更优雅地,使用by

real.seconds <- do.call(rbind, by(df, df$group, function(x) x[2, ]))
Run Code Online (Sandbox Code Playgroud)