【问题标题】:How to find the first and last occurrence in a panel data set in R如何在R中的面板数据集中找到第一个和最后一个出现
【发布时间】:2016-04-04 02:14:39
【问题描述】:

我有一张桌子:

id  time
1   1
1   2
1   5
2   3
2   2
2   7
3   8
3   3
3   14

我想把它转换成:

id  first last
1      1     5
2      3     7
3      8    14

请帮忙!

【问题讨论】:

标签: r


【解决方案1】:

我们可以使用data.table。将'data.frame'转换为'data.table'(setDT(df1)),按'id'分组,我们得到'time'的firstlast

library(data.table)
setDT(df1)[, list(firstocc = time[1L], lastocc = time[.N]),
                    by = id]

或者dplyr,我们使用相同的方法。

library(dplyr)
df1 %>% 
    group_by(id) %>%
    summarise(firstocc = first(time), lastocc = last(time))

或者使用base R(不需要包)

do.call(rbind, lapply(split(df1, df1$id), 
    function(x) data.frame(id = x$id[1],
       firstocc = x$time[1], lastocc = x$time[nrow(x)])))

如果我们需要基于minmax的值(与预期的输出无关),data.table选项是

setDT(df1)[, setNames(as.list(range(time)),
                 c('firstOcc', 'lastOcc')) ,id]

dplyr

df1 %>%
   group_by(id) %>%
   summarise(firstocc = min(time), lastocc = max(time))

【讨论】:

  • 当你按 id 分组时,我不想订购 id。我想让它按它的顺序排列。你能帮我吗?
  • @PreetRajdeo 您可以将“id”转换为factor 类并以相同的顺序设置级别。即df1 %>% group_by(id = factor(id, levels = unique(id))) %>% summarise(firstocc = min(time), lastocc = max(time))
【解决方案2】:

有很多包可以在 R 中执行这种聚合。我们展示如何在没有任何包的情况下执行此操作,然后用一些包展示它。

1) 使用aggregate。不需要包裹。

ag <- aggregate(time ~ id, DF, function(x) c(first = min(x), last = max(x)))

给予:

> ag
  id time.first time.last
1  1          1         5
2  2          2         7
3  3          3        14

ag 是一个两列数据框,其第二列包含一个两列矩阵,其列名为“第一”和“最后”。如果要将其展平为 3 列数据框,请使用:

do.call("cbind", ag)

给予:

     id first last
[1,]  1     1    5
[2,]  2     2    7
[3,]  3     3   14

1a) (1) 的这种变体更紧凑,但牺牲了更难看的列名。

aggregate(time ~ id, DF, range)

2) sqldf

library(sqldf)
sqldf("select id, min(time) first, max(time) last from DF group by id")

给予:

     id first last
[1,]  1     1    5
[2,]  2     2    7
[3,]  3     3   14

3)summaryBy doBy包中的summaryBy很像aggregate

library(doBy)

summaryBy(time ~ id, data = DF, FUN = c(min, max))

给予:

  id time.min time.max
1  1        1        5
2  2        2        7
3  3        3       14

注意:这里是输入 DF 的可重现形式:

Lines <- "id  time
1   1
1   2
1   5
2   3
2   2
2   7
3   8
3   3
3   14"
DF <- read.table(text = Lines, header = TRUE)

更新:添加了 (1a)、(2) 和 (3) 并修复了 (1)。

【讨论】:

    【解决方案3】:

    您可以删除重复项并对其进行重塑

    dd <- read.table(header = TRUE, text = "id  time
    1   1
    1   2
    1   5
    2   3
    2   2
    2   7
    3   8
    3   3
    3   14")
    
    d2 <- dd[!(duplicated(dd$id) & duplicated(dd$id, fromLast = TRUE)), ]
    reshape(within(d2, tt <- c('first', 'last')), dir = 'wide', timevar = 'tt')
    
    #   id time.first time.last
    # 1  1          1         5
    # 4  2          3         7
    # 7  3          8        14
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多