【问题标题】:How to extract certain rows in R without running through the whole data again and again如何在R中提取某些行而不一次又一次地遍历整个数据
【发布时间】:2017-06-02 01:08:40
【问题描述】:

我有一个包含 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

【问题讨论】:

  • 这不只是PERMNOdate 上的重复项,那么如果您要在每个PERMNO 子集中查找date 上的重复项? IE。 duplicated(df[c("PERMNO","date")]) 还是我遗漏了一些微妙之处?
  • 您可以添加您的代码(For 循环)以便我们参考吗?
  • 如果您发布您正在运行的代码会有所帮助,我明白您所描述的内容,但更容易准确地看到它。
  • 我添加了我正在使用的代码@jamzsabb
  • @thelatemail 。您的建议适用于小型数据集。只是当我尝试将它应用于我的 250 万行的原始数据集时,它需要永远运行。我使用了这段代码: array_logic= duplicated(df[c("PERMNO","date")]) r = length(array_logic) newdf = df[FALSE,]
    for(i in 1:r){ if(array_logic[i]==FALSE) {
    newdf = rbind(newdf,df[i,])
    }
    }
    nrow(newdf)

标签: r subset extract rows


【解决方案1】:

对于除海量数据集之外的所有数据集,这应该相当快:

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

【讨论】:

    【解决方案2】:

    对于大型数据集,这应该比 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
    

    【讨论】:

    • 我试过这段代码。这需要很长时间。寻找运行速度更快的东西。
    猜你喜欢
    • 2019-09-12
    • 2022-01-04
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    • 1970-01-01
    • 2017-11-19
    相关资源
    最近更新 更多