删除 r 中有冗余信息的行(不仅仅是重复的)
Delete rows with redundant information in r (not just duplicates)
在此示例数据中:
id<-c(2,2,2,2,2,3,3,3,3,3,3,4,4,4,4)
time<-c(3,5,7,8,9,2,8,10,12,14,18,4,6,7,9)
status<-c('mar','mar','div','c','mar','mar','div','mar','mar','c','div','mar','mar','c','mar')
myd<-data.frame(id,time,status)
id time status
1 2 3 mar
2 2 5 mar
3 2 7 div
4 2 8 c
5 2 9 mar
6 3 2 mar
7 3 8 div
8 3 10 mar
9 3 12 mar
10 3 14 c
11 3 18 div
12 4 4 mar
13 4 6 mar
14 4 7 c
15 4 9 mar
我需要知道这个人什么时候结婚的(如果有两个连续的 'mar' 行之间没有 'div' 任何地方,这个人从未 div 强迫,因此这是同一次婚姻,并且我们不需要重复信息的时间;mar,c,mar 的序列也是如此,因为未检测到 div,因此 child 之前和之后的婚姻是相同的婚姻,因此是第二次一个可以删除)。我怀疑我需要得到 min(time[status=='mar']) 但如果那个人得到 mar,mar,div,mar,div,mar 序列,这将是不正确的(只有2nd mar需要删除,不是第一个之后的所有)。
所以新数据应该类似于
id time status
2 2 5 mar
3 2 7 div
4 2 8 c
5 2 9 mar
6 3 2 mar
7 3 8 div
8 3 10 mar
10 3 14 c
11 3 18 div
13 4 6 mar
14 4 7 c
这是我的方法,只适用于一行
myd2<-myd %>%
group_by(id) %>%
mutate(dum1=ifelse(status=='mar',min(time[status=='mar']),NA),
dum2=cumsum(status=='div'),
flag=ifelse(time>dum1 & dum2==0,1,0))
如果我去掉 dum2==0 那么它删除了太多行。
我将通过在分组数据中创建 lag_status
变量来删除状态未更改的行:
> myd %>%
+ arrange(id, time) %>%
+ group_by(id) %>%
+ mutate(lag_status = lag(status)) %>%
+ ungroup() %>%
+ filter(is.na(lag_status) | status != lag_status) %>%
+ select(-lag_status)
# A tibble: 12 x 3
id time status
<dbl> <dbl> <fct>
1 2 3 mar
2 2 7 div
3 2 8 c
4 2 9 mar
5 3 2 mar
6 3 8 div
7 3 10 mar
8 3 14 c
9 3 18 div
10 4 4 mar
11 4 7 c
12 4 9 mar
我的做法:
library(dplyr)
myd %>%
group_by(id) %>%
arrange(time) %>%
filter(status != lag(status) | is.na(lag(status))) %>%
ungroup() %>%
arrange(id)
Returns:
# A tibble: 12 x 3
id time status
<dbl> <dbl> <chr>
1 2 3 mar
2 2 7 div
3 2 8 c
4 2 9 mar
5 3 2 mar
6 3 8 div
7 3 10 mar
8 3 14 c
9 3 18 div
10 4 4 mar
11 4 7 c
12 4 9 mar
我在你的 post 中读到两个不同的问题。
- 这个人第一次结婚的时间
- 如何制作删除冗余状态信息的列表
您似乎对#1 有解决方案,但实际上您想要#2。
我读 #2 是想过滤掉 id 和状态与前一行相同的行。看起来像:
myd %>%
filter(!(id == lag(id) & status == lag(status))
使用快捷助手功能,
func <- function(x, vals = c("mar", "div")) {
out <- rep(TRUE, length(x))
last <- x[1]
for (ind in seq_along(x)[-1]) {
out[ind] <- x[ind] != last || !x[ind] %in% vals
if (out[ind] && x[ind] %in% vals) last <- x[ind]
}
out
}
我们可以做到
library(data.table)
as.data.table(myd)[, .SD[func(status),], by = .(id)]
# id time status
# <num> <num> <char>
# 1: 2 3 mar
# 2: 2 7 div
# 3: 2 8 c
# 4: 2 9 mar
# 5: 3 2 mar
# 6: 3 8 div
# 7: 3 10 mar
# 8: 3 14 c
# 9: 3 18 div
# 10: 4 4 mar
# 11: 4 7 c
如果你想在 dplyr
中使用它,那么
library(dplyr)
myd %>%
group_by(id) %>%
filter(func(status))
在此示例数据中:
id<-c(2,2,2,2,2,3,3,3,3,3,3,4,4,4,4)
time<-c(3,5,7,8,9,2,8,10,12,14,18,4,6,7,9)
status<-c('mar','mar','div','c','mar','mar','div','mar','mar','c','div','mar','mar','c','mar')
myd<-data.frame(id,time,status)
id time status
1 2 3 mar
2 2 5 mar
3 2 7 div
4 2 8 c
5 2 9 mar
6 3 2 mar
7 3 8 div
8 3 10 mar
9 3 12 mar
10 3 14 c
11 3 18 div
12 4 4 mar
13 4 6 mar
14 4 7 c
15 4 9 mar
我需要知道这个人什么时候结婚的(如果有两个连续的 'mar' 行之间没有 'div' 任何地方,这个人从未 div 强迫,因此这是同一次婚姻,并且我们不需要重复信息的时间;mar,c,mar 的序列也是如此,因为未检测到 div,因此 child 之前和之后的婚姻是相同的婚姻,因此是第二次一个可以删除)。我怀疑我需要得到 min(time[status=='mar']) 但如果那个人得到 mar,mar,div,mar,div,mar 序列,这将是不正确的(只有2nd mar需要删除,不是第一个之后的所有)。
所以新数据应该类似于
id time status
2 2 5 mar
3 2 7 div
4 2 8 c
5 2 9 mar
6 3 2 mar
7 3 8 div
8 3 10 mar
10 3 14 c
11 3 18 div
13 4 6 mar
14 4 7 c
这是我的方法,只适用于一行
myd2<-myd %>%
group_by(id) %>%
mutate(dum1=ifelse(status=='mar',min(time[status=='mar']),NA),
dum2=cumsum(status=='div'),
flag=ifelse(time>dum1 & dum2==0,1,0))
如果我去掉 dum2==0 那么它删除了太多行。
我将通过在分组数据中创建 lag_status
变量来删除状态未更改的行:
> myd %>%
+ arrange(id, time) %>%
+ group_by(id) %>%
+ mutate(lag_status = lag(status)) %>%
+ ungroup() %>%
+ filter(is.na(lag_status) | status != lag_status) %>%
+ select(-lag_status)
# A tibble: 12 x 3
id time status
<dbl> <dbl> <fct>
1 2 3 mar
2 2 7 div
3 2 8 c
4 2 9 mar
5 3 2 mar
6 3 8 div
7 3 10 mar
8 3 14 c
9 3 18 div
10 4 4 mar
11 4 7 c
12 4 9 mar
我的做法:
library(dplyr)
myd %>%
group_by(id) %>%
arrange(time) %>%
filter(status != lag(status) | is.na(lag(status))) %>%
ungroup() %>%
arrange(id)
Returns:
# A tibble: 12 x 3
id time status
<dbl> <dbl> <chr>
1 2 3 mar
2 2 7 div
3 2 8 c
4 2 9 mar
5 3 2 mar
6 3 8 div
7 3 10 mar
8 3 14 c
9 3 18 div
10 4 4 mar
11 4 7 c
12 4 9 mar
我在你的 post 中读到两个不同的问题。
- 这个人第一次结婚的时间
- 如何制作删除冗余状态信息的列表
您似乎对#1 有解决方案,但实际上您想要#2。
我读 #2 是想过滤掉 id 和状态与前一行相同的行。看起来像:
myd %>%
filter(!(id == lag(id) & status == lag(status))
使用快捷助手功能,
func <- function(x, vals = c("mar", "div")) {
out <- rep(TRUE, length(x))
last <- x[1]
for (ind in seq_along(x)[-1]) {
out[ind] <- x[ind] != last || !x[ind] %in% vals
if (out[ind] && x[ind] %in% vals) last <- x[ind]
}
out
}
我们可以做到
library(data.table)
as.data.table(myd)[, .SD[func(status),], by = .(id)]
# id time status
# <num> <num> <char>
# 1: 2 3 mar
# 2: 2 7 div
# 3: 2 8 c
# 4: 2 9 mar
# 5: 3 2 mar
# 6: 3 8 div
# 7: 3 10 mar
# 8: 3 14 c
# 9: 3 18 div
# 10: 4 4 mar
# 11: 4 7 c
如果你想在 dplyr
中使用它,那么
library(dplyr)
myd %>%
group_by(id) %>%
filter(func(status))