【问题标题】:Extract rows for the first occurrence of a variable in a data frame提取数据框中第一次出现变量的行
【发布时间】:2013-11-25 11:55:11
【问题描述】:

我有一个包含两个变量 Date 和 Taxa 的数据框,我想获取每个分类单元第一次出现的日期。由 172 行组成的数据框中有 9 个不同的日期和 40 个不同的分类群,但我的答案应该只有 40 行。

Taxa 是一个因素,Date 是一个日期。

例如,我的数据框(称为“物种”)是这样设置的:

Date          Taxa
2013-07-12    A
2011-08-31    B
2012-09-06    C
2012-05-17    A
2013-07-12    C
2012-09-07    B

我会寻找这样的答案:

Date          Taxa
2012-05-17    A
2011-08-31    B
2012-09-06    C

我尝试使用:

t.first <-  species[unique(species$Taxa),]

它给了我正确的行数,但有重复的分类。如果我只使用 unique(species$Taxa) 它似乎给了我正确的答案,但我不知道它第一次发生的日期。

感谢您的帮助。

【问题讨论】:

    标签: r


    【解决方案1】:
    t.first <- species[match(unique(species$Taxa), species$Taxa),]
    

    应该给你你正在寻找的东西。 match 返回比较向量中第一个匹配项的索引,从而为您提供所需的行。

    【讨论】:

    • 为此,您必须首先确保您的数据框按确定“第一个”实例的列排序。这可以使用species[with(species, order(Date)), ] 来完成,如here 所示
    【解决方案2】:

    在以下命令中,duplicated 为重复的 data$Taxa 值创建逻辑索引。没有相应行的数据框的子集是通过以下方式创建的:

    data[!duplicated(data$Taxa), ]
    

    结果:

            Date Taxa
    1 2012-05-17    A
    2 2011-08-31    B
    3 2012-09-06    C
    

    【讨论】:

    • 为此,您必须首先确保您的数据框按确定“第一个”实例的列排序。这可以使用species[with(species, order(Date)), ] 来完成,如here 所示
    • 我有一个简单的案例,我不在乎我想选择哪一个 - 所以这对我来说很适用,无需先订购。
    • @MonicaHeddneck 如果您不在乎要选择哪一个,则顺序无关紧要。您可以使用这种技术。
    • 是的,先生,我们说的是同一件事!
    【解决方案3】:

    这是一个dplyr 选项,它不依赖于按日期顺序排序的数据并考虑了关系:

    library(dplyr)
    df %>% 
      mutate(Date = as.Date(Date)) %>% 
      group_by(Taxa) %>% 
      filter(Date == min(Date)) %>% 
      slice(1) %>% # takes the first occurrence if there is a tie
      ungroup()
    
    # A tibble: 3 x 2
      Date       Taxa 
      <date>     <chr>
    1 2012-05-17 A    
    2 2011-08-31 B    
    3 2012-09-06 C 
    
    # sample data:
    df <- read.table(text = 'Date          Taxa
                             2013-07-12    A
                             2011-08-31    B
                             2012-09-06    C
                             2012-05-17    A
                             2013-07-12    C
                             2012-09-07    B', header = TRUE, stringsAsFactors = FALSE)
    

    你也可以通过按日期排序得到同样的结果:

    df %>% 
      mutate(Date = as.Date(Date)) %>% 
      group_by(Taxa) %>% 
      arrange(Date) %>% 
      slice(1) %>% 
      ungroup()
    

    【讨论】:

      【解决方案4】:

      这应该可以解决问题:

      # Create some dummy data:
      
      # Create some dates 
      Date=as.POSIXct(c("2013-07-12","2011-08-31","2012-09-06","2009-01-01",
                        "2012-05-17","2013-07-12","2012-09-07","2013-02-02"))
      
      # Create unique taxa
      Taxa=rep(c("A","B","C","D"),2)
      
      # Combine the two into a dataframe
      data=as.data.frame(list(Date=Date,Taxa=Taxa))
      
      # this returns a numeric vector of the minimum dates
      xx=tapply(data$Date,list(data$Taxa),min)
      
      # And this will return a dataframe with the first occurence
      # of your taxa (or variables)
      as.data.frame(list(Date=as.POSIXct(xx,origin="1970-01-01"),
                         Taxa=names(xx)))
      

      注意:您可以在 tapply 中添加 simple=T 以返回 POSIXt 对象,但它返回一个列表。更多信息可以在这里找到: Unexpected behaviour of min, tapply and POSIXct/POSIXlt classes?

      【讨论】:

        【解决方案5】:

        这是使用data.table的解决方案:

        library(data.table)
        setDT(species)
        species[, .SD[which.min(Date)], by = Taxa]
        #    Taxa       Date
        # 1:    A 2012-05-17
        # 2:    B 2011-08-31
        # 3:    C 2012-09-06
        

        数据:

        species <- data.frame(
          Date = as.Date(c("2013-07-12", "2011-08-31", "2012-09-06", 
                           "2012-05-17", "2013-07-12", "2012-09-07")), 
          Taxa = c("A", "B", "C", "A", "C", "B")
        )
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-02-08
          • 2018-12-21
          • 1970-01-01
          • 2021-10-16
          • 2023-01-23
          • 1970-01-01
          相关资源
          最近更新 更多