2

我有一个简单的数据框,其中包含两个向量“速度”和“ID”,如下所示:

mydata
ID     Speed
1   1  6.031847
2   1  7.050654
3   1  7.769475
4   1  8.838968
5   1  9.956571
6   1 11.146864
7   1 11.967616
8   1 13.078422
9   1 14.214301
10  1 14.974159
11  2 16.048627
12  2 17.070484
..  . .........

我想使用以下方法制作速度值前 20% 的数据帧的子集:

subset0.20<-subset(mydata, Speed > quantile(Speed, prob = 1 - 20/100, na.rm=T))

但我不希望它用于整个数据集,因为这会给我返回每个 ID 的不相等数量的值。

因此,必须为每个 ID 计算前 20% 的值,然后将每个 ID 的结果组合到一个新的数据帧中。然后这个数据框将包含 8 行(这是我的原始数据集的 20%,它有 40 行)

所以我做了一些指甲咬伤并拔出一些头发并尝试了“for循环”,例如:

for(i in 1:length(ID)){
   subset0.80<-subset(mydata[i], GForce > quantile(Speed, prob = 1 - 20/100, na.rm=T))
     }

和应用之类的东西:

apply(mydata$Speed, 1 ,function(x) (subset(x > quantile(Speed, prob = 1 - 20/100, na.rm=T))))

但我只是对 R 缺乏经验才能让它发挥作用。任何可以帮助我并向我解释我在这里做错的事情的人吗?

dput(mydata)
structure(list(ID = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 
2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4), Speed = c(6.03184705225504, 7.05065401832249, 
7.76947483668907, 8.83896842017956, 9.95657139135043, 11.1468640558647, 
11.9676155772803, 13.0784218506988, 14.2143010441769, 14.9741594881612, 
16.0486271520862, 17.0704843261466, 17.9324808839116, 19.1169673939822, 
20.0528330256269, 20.9320440815571, 22.0379467007031, 22.962355355126, 
24.0764744246649, 25.1182530133201, 26.0456043859692, 26.9528777031822, 
27.9414746553538, 29.129640434174, 29.9443040639644, 30.9226103003052, 
31.9932286699133, 32.9925644101585, 33.9930708538141, 35.0124438238874, 
35.9215486087666, 36.9015465999988, 38.1044534443389, 39.0368063088987, 
40.272189714015, 40.8993100278334, 41.9790311160737, 43.1027190745506, 
43.8575622361406, 45.0499599122387)), .Names = c("ID", "Speed"
), row.names = c(NA, -40L), class = "data.frame")
4

5 回答 5

4

使用by,您可以subset为每个 ID 调用函数。然后你可以bind使用do.callwhich 将结果转换list为 a data.frame

你可以这样做:

do.call(rbind,by(mydata,mydata$ID,FUN= function(x)
      subset(x, Speed > quantile(Speed, prob = 1 - 20/100, na.rm=T))))

     ID    Speed
1.9   1 14.21430
1.10  1 14.97416
2.19  2 24.07647
2.20  2 25.11825
3.29  3 33.99307
3.30  3 35.01244
4.39  4 43.85756
4.40  4 45.04996
于 2013-04-11T09:42:38.670 回答
4

几种方法可以做到这一点(太多了,可能会令人困惑)。这是一个使用ave

GetMe <- with(mydata, 
              ave(Speed, ID, FUN = function(x) 
                x > quantile(x, prob = 1 - 20/100, na.rm = TRUE)))

mydata[GetMe == 1, ]
#    ID    Speed
# 9   1 14.21430
# 10  1 14.97416
# 19  2 24.07647
# 20  2 25.11825
# 29  3 33.99307
# 30  3 35.01244
# 39  4 43.85756
# 40  4 45.04996

这个data.table包也很适合这个:

library(data.table)
DT <- data.frame(mydata)
DT[, list(Speed = Speed[Speed > quantile(Speed, prob = 1 - 20/100, na.rm = TRUE)]), by = "ID"]
#    ID    Speed
# 1:  1 14.21430
# 2:  1 14.97416
# 3:  2 24.07647
# 4:  2 25.11825
# 5:  3 33.99307
# 6:  3 35.01244
# 7:  4 43.85756
# 8:  4 45.04996
于 2013-04-11T09:46:13.920 回答
2

一种方法是使用split您的数据ID,然后lapply在数据框的结果列表中使用以找到您的前 20% 分位数。最后,使用do.callandrbind将结果绑定在一起。

result <- do.call(rbind, lapply(split(mydata, mydata$ID), function(X) {
    subset(X, Speed > quantile(Speed, prob = 1 - 20/100, na.rm = T))
}))

result
##      ID    Speed
## 1.9   1 14.21430
## 1.10  1 14.97416
## 2.19  2 24.07647
## 2.20  2 25.11825
## 3.29  3 33.99307
## 3.30  3 35.01244
## 4.39  4 43.85756
## 4.40  4 45.04996
于 2013-04-11T09:47:30.630 回答
2

尝试这个

library(plyr)

> ddply(mydata, .(ID), function(x) subset(x, Speed > quantile(Speed, prob = 1 - 20/100, na.rm=T)))
  ID    Speed
1  1 14.21430
2  1 14.97416
3  2 24.07647
4  2 25.11825
5  3 33.99307
6  3 35.01244
7  4 43.85756
8  4 45.04996

@SimonO101

尝试使用meltfromreshape2

res <- aggregate( Speed ~ ID , data = mydata , function(x) { y <- rev( seq( length(x) , by = -1 ,length.out =(length(x) / 5) ) )  ; cbind(x[y[1]],x[y[2]]) })

> melt(res, id.vars="ID")
  ID variable    value
1  1    Speed 14.21430
2  2    Speed 24.07647
3  3    Speed 33.99307
4  4    Speed 43.85756
5  1    Speed 14.97416
6  2    Speed 25.11825
7  3    Speed 35.01244
8  4    Speed 45.04996

可能,在那之后,您可能想要删除第二列:-)。

于 2013-04-11T09:51:26.703 回答
1

我勒个去。aggregate这是使用R的单行解决方案base。每个 ID 一行的数据格式略有不同,每个速度值在它自己的列中:

aggregate( Speed ~ ID , data = mydata , function(x) { y <- rev( seq( length(x) , by = -1 ,length.out =(length(x) / 5) ) )  ; cbind(x[y[1]],x[y[2]]) } )

  ID  Speed.1  Speed.2
#1  1 14.21430 14.97416
#2  2 24.07647 25.11825
#3  3 33.99307 35.01244
#4  4 43.85756 45.04996
于 2013-04-11T10:01:33.990 回答