r-如何在每组中选择不同数量的观察
我对来自sas的r比较陌生 我需要在每组中选择不同数量的观察结果。组由两个变量的值标识r-如何在每组中选择不同数量的观察,r,data-management,R,Data Management,我对来自sas的r比较陌生 我需要在每组中选择不同数量的观察结果。组由两个变量的值标识 ToSelect <- data.frame( key1=c(1,1,1,1,1,2,2,2,2,2,2,2), key2=c("a","a","b","b","b","a","a","a","a","b","b","b"), var1=c(2
ToSelect <- data.frame(
key1=c(1,1,1,1,1,2,2,2,2,2,2,2),
key2=c("a","a","b","b","b","a","a","a","a","b","b","b"),
var1=c(2,3,4,6,2,7,8,5,7,1,8,5)
)
NumObs <- data.frame(
key1=c(1,1,2,2),
key2=c("a","b","a","b"),
NumObs=c(1,2,2,1)
)
我试着从问题中选择R中每个级别的前80个观察值
ToSelect <- merge(x=ToSelect,y=NumObs,by=c("key1","key2"))
library(plyr)
Selected <- ddply(ToSelect, .(key1,key2), head, n = NumObs)
给
错误:lengthn==1L不是真的
对于专家来说,这可能是一个明显的错误,对于一个标量,一个向量
从同一个问题出发,我试着:
Selected <- do.call(
rbind,
lapply(split(ToSelect, c(ToSelect$key1,ToSelect$key2)), head, NumObs)
)
给
错误:lengthn==1L不是真的。
此外:警告消息:在
split.defaultx=seq_lennrowx,f=f,drop=drop,…:数据
长度不是拆分变量的倍数
所以,和以前一样的错误,加上多个东西,如果组的长度不同,我不能使用split
然后,我按小组找到了问题观察编号,在我的案例中,我无法使rle/顺序答案起作用,但调整了ddply答案:
ToSelect <- ddply(ToSelect, .(key1, key2), function(z){
cbind(var1=z$var1,NumObs=z$NumObs,
data.frame(
SeqNum = seq_along(z$key2)
)
)
}
)
Selected <- ToSelect[ToSelect$SeqNum<=ToSelect$NumObs,c("key1","key2","var1")]
这很有效
显然,我的真实数据要大得多,那么有没有其他更好的方法呢?
谢谢 以下是一种方法,您可以使用该方法从每组key1和key2对中选择n个观测值。在这种情况下,n由NumObs data.frame中的NumObs指定 为了做到这一点,我使用了dplyr包,但肯定还有其他方法可以做同样的事情 安装软件包并将其加载到库中:
require(dplyr)
I first join=将两个data.frames合并在一起:
df <- left_join(ToSelect, NumObs, by=c("key1", "key2"))
如果希望生成的data.frame不包含NumObs列,可以将其调整为:
df <- df %.% group_by(key1, key2) %.% filter(1:n() <= NumObs) %.% select(-NumObs)
如果您希望提高效率,我建议您查看data.table包。这个问题的一个相当直接的解决方案可以是:
#Convert objects to data.table
require("data.table")
ToSelect <- data.table(ToSelect)
NumObs <- data.table(NumObs)
#Merge data
ToSelect <- merge(ToSelect,NumObs,by=c("key1","key2"),all.x=T)
#Provide intra-group ordering variable
ToSelect[,Grp.Seq:=seq(1:.N),by=c("key1","key2")]
Selected <- ToSelect[NumObs>=Grp.Seq]
Selected
key1 key2 var1 NumObs Grp.Seq
1: 1 a 2 1 1
2: 1 b 4 2 1
3: 1 b 6 2 2
4: 2 a 7 2 1
5: 2 a 8 2 2
6: 2 b 1 1 1
如果您对R还是新手,并且经常使用大型数据集,那么从一开始就学习data.table可能是有意义的。我在工作中使用非常大的数据集,而data.frame类在我所做的大部分工作中并不实用。如果需要,可以很容易地在data.frame和data.table之间切换。如果您正在尝试执行我认为您正在尝试执行的操作,那么data.table将非常有用。这个小小的一行程序基本上是根据NumObs表中给出的所需观察数,按组随机抽样var1的值。尝试:
# Load package
require(data.table)
# Make your data.frames into data.tables
ts <- data.table( ToSelect , key = c( "key1","key2"))
no <- data.table( NumObs , key = c( "key1","key2") )
# Join together based on key columns and sample by group
no[ts][ , sample( var1 , NumObs , TRUE ) , by = c("key1","key2") ]
# key1 key2 V1
#1: 1 a 2
#2: 1 b 6 #|_ Two observations of group 1b
#3: 1 b 6 #|
#4: 2 a 5 #|_ Two observations of group 2a
#5: 2 a 8 #|
#6: 2 b 5
如果您不想如上所述使用替换进行采样,请查看组1b的值-它们相同,然后删除sample的真参数,这样您就不能选择超过每组观察总数的更多观察值。目前dplyr答案有效,但我肯定会查看data.table,谢谢!
# Load package
require(data.table)
# Make your data.frames into data.tables
ts <- data.table( ToSelect , key = c( "key1","key2"))
no <- data.table( NumObs , key = c( "key1","key2") )
# Join together based on key columns and sample by group
no[ts][ , sample( var1 , NumObs , TRUE ) , by = c("key1","key2") ]
# key1 key2 V1
#1: 1 a 2
#2: 1 b 6 #|_ Two observations of group 1b
#3: 1 b 6 #|
#4: 2 a 5 #|_ Two observations of group 2a
#5: 2 a 8 #|
#6: 2 b 5