首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >按组选择数据框中的第一行和最后一行

按组选择数据框中的第一行和最后一行
EN

Stack Overflow用户
提问于 2011-11-21 02:52:31
回答 4查看 51.1K关注 0票数 54

如何为以下数据帧中的每个唯一id选择第一行和最后一行?

代码语言:javascript
复制
tmp <- structure(list(id = c(15L, 15L, 15L, 15L, 21L, 21L, 22L, 22L, 
22L, 23L, 23L, 23L, 24L, 24L, 24L, 24L), d = c(1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), gr = c(2L, 1L, 
1L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 2L, 1L, 1L, 1L, 2L), mm = c(3.4, 
4.9, 4.4, 5.5, 4, 3.8, 4, 4.9, 4.6, 2.7, 4, 3, 3, 2, 4, 2), area = c(1L, 
2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 3L)), .Names = c("id", 
"d", "gr", "mm", "area"), class = "data.frame", row.names = c(NA, 
-16L))
tmp
#>    id d gr  mm area
#> 1  15 1  2 3.4    1
#> 2  15 1  1 4.9    2
#> 3  15 1  1 4.4    1
#> 4  15 1  1 5.5    2
#> 5  21 1  1 4.0    2
#> 6  21 1  2 3.8    2
#> 7  22 1  1 4.0    2
#> 8  22 1  1 4.9    2
#> 9  22 1  2 4.6    2
#> 10 23 1  1 2.7    2
#> 11 23 1  1 4.0    2
#> 12 23 1  2 3.0    2
#> 13 24 1  1 3.0    2
#> 14 24 1  1 2.0    3
#> 15 24 1  1 4.0    2
#> 16 24 1  2 2.0    3
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-11-21 03:04:59

plyr解决方案(tmp是您的数据框架):

代码语言:javascript
复制
library("plyr")
ddply(tmp, .(id), function(x) x[c(1, nrow(x)), ])
#    id d gr  mm area
# 1  15 1  2 3.4    1
# 2  15 1  1 5.5    2
# 3  21 1  1 4.0    2
# 4  21 1  2 3.8    2
# 5  22 1  1 4.0    2
# 6  22 1  2 4.6    2
# 7  23 1  1 2.7    2
# 8  23 1  2 3.0    2
# 9  24 1  1 3.0    2
# 10 24 1  2 2.0    3

或使用dplyr (另请参阅here):

代码语言:javascript
复制
library("dplyr")
tmp %>%
group_by(id) %>%
slice(c(1, n())) %>%
ungroup()
# # A tibble: 10 × 5
#       id     d    gr    mm  area
#    <int> <int> <int> <dbl> <int>
# 1     15     1     2   3.4     1
# 2     15     1     1   5.5     2
# 3     21     1     1   4.0     2
# 4     21     1     2   3.8     2
# 5     22     1     1   4.0     2
# 6     22     1     2   4.6     2
# 7     23     1     1   2.7     2
# 8     23     1     2   3.0     2
# 9     24     1     1   3.0     2
# 10    24     1     2   2.0     3
票数 42
EN

Stack Overflow用户

发布于 2011-11-21 21:42:37

快速而简短的data.table解决方案:

代码语言:javascript
复制
tmp[, .SD[c(1,.N)], by=id]

其中.SD表示(D)ata的每个(S)子集,.N是每个组中的行数,tmpdata.table;例如,由fread()默认提供或通过使用setDT()转换data.frame来提供。

请注意,如果一个组只包含一行,该行将在输出中出现两次,因为该行既是该组的第一行,也是最后一行。为了避免这种情况下的重复,感谢@Thell:

代码语言:javascript
复制
tmp[, .SD[unique(c(1,.N))], by=id]

或者,下面的代码为.N==1特殊情况提供了明确的逻辑:

代码语言:javascript
复制
tmp[, if (.N==1) .SD else .SD[c(1,.N)], by=id]

您不需要在if的第一部分中使用.SD[1],因为在这种情况下,.N1,所以.SD必须只有一行。

如果愿意,您可以将j包装在{}中,并在{}中包含整个代码页面。只要{}中的最后一个表达式返回一个要堆叠的类似list的对象(比如普通的listdata.tabledata.frame)。

代码语言:javascript
复制
tmp[, { ...; if (.N==1) .SD else .SD[c(1,.N)] } , by=id]
票数 113
EN

Stack Overflow用户

发布于 2020-02-28 15:57:19

另一种利用dplyr的方法可以是:

代码语言:javascript
复制
tmp %>%
 group_by(id) %>%
 filter(1:n() %in% range(1:n()))

      id     d    gr    mm  area
   <int> <int> <int> <dbl> <int>
 1    15     1     2   3.4     1
 2    15     1     1   5.5     2
 3    21     1     1   4       2
 4    21     1     2   3.8     2
 5    22     1     1   4       2
 6    22     1     2   4.6     2
 7    23     1     1   2.7     2
 8    23     1     2   3       2
 9    24     1     1   3       2
10    24     1     2   2       3

或者与使用row_number()的想法相同

代码语言:javascript
复制
tmp %>%
 group_by(id) %>%
 filter(row_number() %in% range(row_number()))

或者使用slice()执行操作

代码语言:javascript
复制
tmp %>%
 group_by(id) %>%
 slice(c(which.min(1:n()), which.max(1:n())))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8203818

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档