如何在R中提取某些行而不是一次又一次地遍历整个数据

时间:2017-06-02 01:08:41

标签: r subset extract rows

我有一个250万行的数据框(df)。示例数据框如下所示:

PERMNO <- c(10000,10000,10001,10001,10001,10001, 10002,10002,10002)

TICKER <- c('OMFGA','OMFGA', 'GFGC', 'GFGC', 'GFGC', 'GFGC', 'MBNC', 'MBNC', 'MBNC')

date <- as.Date(c('1986-03-31','1986-04-30','1986-01-31', '1986-01-31', '1986-03-31', '1986-04-30', '1986-04-30','1986-05-30', '1986-05-30'))

df = data.frame(PERMNO, date, TICKER)

在这个例子中,有3个独特的PERMNO。现在我需要提取给定PERMNO的所有数据,并检查是否有任何重复日期。我的目的是删除具有特定PERMNO的重复日期的行。我为所有独特的PERMNO做了这个操作

我的方法:我使用子集函数来提取特定PERMNO的数据,然后检查日期中的重复项。但是使用这种方法,我的代码每次都会遍历整个数据(原始数据集中有250万行),以便为特定的PERMNO提取数据。有没有更短的方法来做到这一点?由于我有22000个唯一的PERMNO,因此代码将永远在For循环中运行。

以下是我使用的代码:

uniqueperm = unique(df$PERMNO)

lenperm = length(uniqueperm)

data_final = df[FALSE,]  

for(i in 1:lenperm){

        perm = uniqueperm[i]
        df1 = filter(df, PERMNO == perm) 
        df1 = subset(df1,!duplicated(df1$date))
        data_final = rbind(data_final,df1)
        df1 = df1[FALSE,]
} 

data_final

2 个答案:

答案 0 :(得分:3)

除了大量数据集外,这应该相当快:

df[!duplicated(df[c("PERMNO","date")]),]
#  PERMNO       date TICKER
#1  10000 1986-03-31  OMFGA
#2  10000 1986-04-30  OMFGA
#3  10001 1986-01-31   GFGC
#5  10001 1986-03-31   GFGC
#6  10001 1986-04-30   GFGC
#7  10002 1986-04-30   MBNC
#8  10002 1986-05-30   MBNC

与您拥有的类似数据的基本时间:

df2 <- data.frame(PERMNO=sample(1:22000,2.5e6,replace=TRUE), date=1:2.5e6)
nrow(df2)
#[1] 2500000
length(unique(df2$PERMNO))
#[1] 22000
system.time(df2[!duplicated(df2[c("PERMNO","date")]),])
#   user  system elapsed 
#   3.48    0.08    3.56

答案 1 :(得分:1)

这应该比大数据集的for循环更快:

dates <- lapply(split(df, df$PERMNO), '[[', "date") 
df2 <-mapply(function(x,y)x[!y,], 
           split(df,df$PERMNO), 
           lapply(dates, duplicated), 
           SIMPLIFY = FALSE)

do.call(rbind, df2)

#         PERMNO       date TICKER
# 10000.1  10000 1986-03-31  OMFGA
# 10000.2  10000 1986-04-30  OMFGA
# 10001.3  10001 1986-01-31   GFGC
# 10001.5  10001 1986-03-31   GFGC
# 10001.6  10001 1986-04-30   GFGC
# 10002.7  10002 1986-04-30   MBNC
# 10002.8  10002 1986-05-30   MBNC