首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >R中每个观测值的第一行子集

R中每个观测值的第一行子集
EN

Stack Overflow用户
提问于 2014-08-27 17:35:43
回答 4查看 79关注 0票数 2

我有数据框架:

代码语言:javascript
运行
复制
Observations Value
obs 1     1
obs 1     2
obs 1     3
obs 1     4
obs 2     5
obs 2     6
obs 2     7
obs 3     8
obs 3     9

是否可能只对每个观测的第一行进行子集?

以至于我得到了:

代码语言:javascript
运行
复制
Observations Value
obs 1     1
obs 2     5
obs 3     8
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-08-27 17:43:59

我认为您希望为此使用duplicated函数。

代码语言:javascript
运行
复制
> df[!duplicated(df$Observations), ]
#   Observations Value
# 1        obs 1     1
# 5        obs 2     5
# 8        obs 3     8

另一种选择是

代码语言:javascript
运行
复制
> unsplit(lapply(split(df, df$Observations), `[`, 1,), levels(df$Observations))
#   Observations Value
# 1        obs 1     1
# 5        obs 2     5
# 8        obs 3     8

虽然后者使用了一个循环,并且会比duplicated方法慢很多卫星。

do.call("rbind", lapply(split(df, df$Observations), "[", 1,))也可以使用。

票数 3
EN

Stack Overflow用户

发布于 2014-08-27 18:20:19

也可以为此使用dplyr

代码语言:javascript
运行
复制
library(dplyr)
group_by(dat, Observations) %>% filter(row_number() == 1)
#Source: local data frame [3 x 2]
#Groups: Observations
#
#  Observations Value
#1        obs_1     1
#2        obs_2     5
#3        obs_3     8

通过@akrun使用示例数据:

代码语言:javascript
运行
复制
set.seed(49)
dat <- data.frame(Observations=sample(LETTERS, 1e5, replace=TRUE), value=rnorm(1e5))
library(microbenchmark)
library(data.table)
f1 <- function(){aggregate(value~Observations, head, 1, data=dat)}
f2 <- function(){dat[!duplicated(dat$Observations), ]}  
f3 <- function(){DT <- data.table(dat, key='Observations')
                 DT[J(unique(Observations)), mult="first"]}
f4 <- function(){group_by(dat, Observations) %>% filter(row_number() == 1)}

microbenchmark(f1(), f2(), f3(), f4(), unit="relative")
#Unit: relative
#expr         min         lq     median         uq        max neval
#f1() 149.0736206 145.881588 143.122352 138.611025 108.063314   100
#f2()   1.8248371   1.805648   1.783553   1.736195   1.554765   100
#f3()   0.9861738   1.259007   1.279011   1.270937  11.535428   100
#f4()   1.0000000   1.000000   1.000000   1.000000   1.000000   100

在@Arun的评论之后,使用另一个data.table-approach更新:

代码语言:javascript
运行
复制
set.seed(49)
dat <- data.frame(Observations=sample(LETTERS, 1e5, replace=TRUE), value=rnorm(1e5))
library(microbenchmark)
f1 <- function(){aggregate(value~Observations, head, 1, data=dat)}
f2 <- function(){dat[!duplicated(dat$Observations), ]}  
f3 <- function(){DT <- data.table(dat, key='Observations')
                 DT[J(unique(Observations)), mult="first"]}
f4 <- function(){group_by(dat, Observations) %>% filter(row_number() == 1)}
f5 <- function() {dt = as.data.table(dat); unique(dt, by="Observations")}

microbenchmark(f1(), f2(), f3(), f4(), f5(), unit="relative")
#Unit: relative
#expr        min         lq     median         uq        max neval
#f1() 274.036916 247.499012 234.616587 227.094582 8.54993826   100
#f2()   3.065027   3.059164   2.881088   2.797630 0.10404962   100
#f3()   2.122190   2.197721   2.105737   2.056280 0.08284540   100
#f4()   1.731631   1.703298   1.616957   1.584485 0.07353602   100
#f5()   1.000000   1.000000   1.000000   1.000000 1.00000000   100
票数 2
EN

Stack Overflow用户

发布于 2014-08-27 17:37:42

这里有一种使用R基函数的方法

代码语言:javascript
运行
复制
> aggregate(Value~Observations, head, 1, data=df)  # df is your data.frame
  Observations Value
1         obs1     1
2         obs2     5
3         obs3     8

这个会给你同样的输出

代码语言:javascript
运行
复制
> aggregate(Value~Observations, function(x) x[1], data=df)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25533619

复制
相关文章

相似问题

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