R-保留由多个变量确定的每个组的第一个观察值(Stata等效“bys var1 var2:如果”u n==1“则保留)
因此,我目前在R中面临一个问题,我确切地知道如何在Stata中处理这个问题,但在R中已经浪费了两个多小时 使用下面的data.frame,我想要的结果是准确地获得每组的第一个观察值,而组由多个变量组成,并且必须按另一个变量排序,即data.frame mydata通过以下方式获得:R-保留由多个变量确定的每个组的第一个观察值(Stata等效“bys var1 var2:如果”u n==1“则保留),r,stata,R,Stata,因此,我目前在R中面临一个问题,我确切地知道如何在Stata中处理这个问题,但在R中已经浪费了两个多小时 使用下面的data.frame,我想要的结果是准确地获得每组的第一个观察值,而组由多个变量组成,并且必须按另一个变量排序,即data.frame mydata通过以下方式获得: id <- c(1,1,1,1,2,2,3,3,4,4,4) day <- c(1,1,2,3,1,2,2,3,1,2,3) value <- c(12,10,15,20,40,30,22,24,1
id <- c(1,1,1,1,2,2,3,3,4,4,4)
day <- c(1,1,2,3,1,2,2,3,1,2,3)
value <- c(12,10,15,20,40,30,22,24,11,11,12)
mydata <- data.frame(id, day, value)
通过仅保留具有一个或多个重复组标识符的行中的一行(此处仅为行[1]:(id,day)=(1,1))
,首先对值进行排序(以便保留具有最低值的行)
在Stata,这将是:
bys id day (value): keep if _n == 1
我找到了一个,如果我首先生成一个组标识符,它会正确地执行此操作:
mydata$id1 <- paste(mydata$id,"000",mydata$day, sep="") ### the single group identifier
myid.uni <- unique(mydata$id1)
a<-length(myid.uni)
last <- c()
for (i in 1:a) {
temp<-subset(mydata, id1==myid.uni[i])
if (dim(temp)[1] > 1) {
last.temp<-temp[dim(temp)[1],]
}
else {
last.temp<-temp
}
last<-rbind(last, last.temp)
}
last
mydata$id1我会订购data.frame
,在这一点上,您可以通过查看:
mydata <- mydata[with(mydata, do.call(order, list(id, day, value))), ]
do.call(rbind, by(mydata, list(mydata$id, mydata$day),
FUN=function(x) head(x, 1)))
或者,从零开始,您可以按以下方式使用data.table
:
DT <- data.table(id, day, value, key = "id,day")
DT[, n := rank(value, ties.method="first"), by = key(DT)][n == 1]
DT包dplyr使这类事情变得更容易
library(dplyr)
mydata %>% group_by(id, day) %>% filter(row_number(value) == 1)
请注意,此命令在R中比在Stata中需要更多的内存:在R中,创建数据集的新副本,而在Stata中,行被就地删除。使用data.table,假设mydata
对象已按您所需的方式排序,另一种方法是:
library(data.table)
mydata <- data.table(my.data)
mydata <- mydata[, .SD[1], by = .(id, day)]
库(data.table)
mydata%
解组()
如果不将ungroup()
添加到末尾,dplyr的分组结构仍将存在,并且可能会打乱后续的一些功能。使用的替代方法是:完成任务,但所用的时间与我最初发布的代码一样长。我将不得不让IT人员安装data.table来查看这一点,如果效果更好,我将在稍后与您联系。@iraserd,我也很难相信这些方法中的任何一种都需要1.5个小时。你能添加更多关于你的数据的信息吗?嗯,我在大约15分钟后放弃了我最初发布的for-loop方法,到那时它已经处理了大约12k的80k个观测值。@Anada Mahto,好的,所以对于我的数据集的一个小的子样本,你的所有3个备选方案都工作得很好。然而,在完整的数据集(大约500k个观测值)上,by()和DT[]似乎比ave()花费的时间要长得多。Ave()大约5分钟后才结束,而我分别在大约10分钟后通过()和DT[]中止。这对我来说是正确的答案,谢谢@伊拉瑟德,我觉得这很奇怪。“data.table”包应该非常高效。您有多少“id”变量的唯一组合?在我对500kdata.frame
的测试中,“data.table”方法我得到了约1分钟,而ave
方法我得到了约2分钟。我是一个Stata人,但我不认为通过暗示R是差劲的来吸引R用户,即使是对于一个非常具体的详细任务。最好是暗示一定有一个整洁的R方法来做,只是你没有识别它。@NickCox,我不是有意侮辱R,如果这是听起来的话。在过去的两周里,我一直在从Stata进行迁移,但仍在努力获得正确的基本功能。对于迁移的初学者来说,虽然可以在R中有效地使用for
循环,但如果这是您的第一个选择,它可能不是最有效的方法。@iraserd无疑;我只是建议如何影响人们并鼓励他们回答你的问题。这是什么%>%?错误结果:找不到已加载库(dplyr)的函数“%>%”。是因为我还在运行3.0.2吗?可能吧。它将对象放在左边,作为函数的第一个参数放在右边。第一行相当于slice(arrange(group_by(mydata,id,day),value),1)
Ranks <- with(mydata, ave(value, id, day, FUN = function(x)
rank(x, ties.method="first")))
mydata[Ranks == 1, ]
library(dplyr)
mydata %>% group_by(id, day) %>% filter(row_number(value) == 1)
library(data.table)
mydata <- data.table(my.data)
mydata <- mydata[, .SD[1], by = .(id, day)]
library(dplyr)
mydata <- mydata %>%
group_by(id, day) %>%
slice(1) %>%
ungroup()