使用R在数据框中对行进行子集和重复

问题描述 投票:4回答:4

假设我们有以下数据,列名为“id”,“time”和“x”:

df<-
structure(
list(
id = c(1L, 1L, 1L, 2L, 2L, 3L, 3L),
time = c(20L, 6L, 7L, 11L, 13L, 2L, 6L),
x = c(1L, 1L, 0L, 1L, 1L, 1L, 0L)
),
.Names = c("id", "time", "x"),
class = "data.frame",
row.names = c(NA,-7L)
)

每个id都有多个时间和x的观察值。我想提取每个id的最后一个观察结果并形成一个新的数据帧,根据原始数据中每个id的观察次数重复这些观察。我可以使用以下代码提取每个id的最后一个观察结果

library(dplyr) 
df<-df%>% 
group_by(id) %>% 
filter( ((x)==0 & row_number()==n())| ((x)==1 & row_number()==n()))

尚未解决的问题是重复方面。预期的输出看起来像

df <-
structure(
list(
id = c(1L, 1L, 1L, 2L, 2L, 3L, 3L),
time = c(7L, 7L, 7L, 13L, 13L, 6L, 6L),
x = c(0L, 0L, 0L, 1L, 1L, 0L, 0L)
),
.Names = c("id", "time", "x"),
class = "data.frame",
row.names = c(NA,-7L)
)

感谢您的帮助。

r dataframe
4个回答
4
投票

我们可以使用ave找到每个maxID行号,并从数据帧中对其进行子集化。

df[ave(1:nrow(df), df$id, FUN = max), ]

#    id time x
#3    1    7 0
#3.1  1    7 0
#3.2  1    7 0
#5    2   13 1
#5.1  2   13 1
#7    3    6 0
#7.1  3    6 0

2
投票

你可以使用last()来获取每个id中的最后一行。

df %>%
    group_by(id) %>%
    mutate(time = last(time),
           x = last(x))

因为last(x)返回单个值,所以它会扩展为填充mutate()调用中的所有行。

这也可以使用mutate_at应用于任意数量的变量:

df %>%
    group_by(id) %>%
    mutate_at(vars(-id), ~ last(.))

2
投票

slice将成为你在tidyverse中的朋友,我估计:

df %>%
  group_by(id) %>%
  slice(rep(n(),n()))
## A tibble: 7 x 3
## Groups:   id [3]
#     id  time     x
#  <int> <int> <int>
#1     1     7     0
#2     1     7     0
#3     1     7     0
#4     2    13     1
#5     2    13     1
#6     3     6     0
#7     3     6     0

data.table中,您还可以使用连接的mult=参数:

library(data.table)
setDT(df)
df[df[,.(id)], on="id", mult="last"]
#   id time x
#1:  1    7 0
#2:  1    7 0
#3:  1    7 0
#4:  2   13 1
#5:  2   13 1
#6:  3    6 0
#7:  3    6 0

在基地R,merge也会让你到那里:

merge(df["id"], df[!duplicated(df$id, fromLast=TRUE),])
#  id time x
#1  1    7 0
#2  1    7 0
#3  1    7 0
#4  2   13 1
#5  2   13 1
#6  3    6 0
#7  3    6 0

2
投票

使用data.table你可以试试

library(data.table)
setDT(df)[,.(time=rep(time[.N],.N), x=rep(x[.N],.N)), by=id]
   id time  x
1:  1    7  0
2:  1    7  0
3:  1    7  0
4:  2   13  1
5:  2   13  1
6:  3    6  0
7:  3    6  0

关注@thelatemai,为避免命名列,您也可以尝试

df[, .SD[rep(.N,.N)], by=id]
   id time x
1:  1    7 0
2:  1    7 0
3:  1    7 0
4:  2   13 1
5:  2   13 1
6:  3    6 0
7:  3    6 0
© www.soinside.com 2019 - 2024. All rights reserved.