我有如下一个数据帧。我想设置一个最小行变量(姑且称之为min_row
)每个ID
,这意味着每个ID
至少应有min_row
记录。如果没有,我想插入一行与另一列ID
值NA
(这里是subject
列)。
min_row_id=3
df
ID subject
1 A1
1 A2
2 A1
3 A1
3 A2
3 A3
3 A4
resutl:
ID subject
1 A1
1 A2
1 NA
2 A1
2 NA
2 NA
3 A1
3 A2
3 A3
3 A4
因此,每个ID
至少有3条记录。
我怎样才能做到这一点R中?谢谢
下面是使用tidyr::complete
一种方式。我们创建了计数记录每个record_number
组ID
列。然后complete
将让我们填写所有缺少的行,所以每个组有许多记录作为拥有最(如果没有组有3条记录,它们填充到3行)的组。然后,我们过滤掉无关行超过3%加入该组。
library(tidyverse)
tbl <- read_table2(
"ID subject
1 A1
1 A2
2 A1
3 A1
3 A2
3 A3
3 A4"
)
tbl %>%
group_by(ID) %>%
mutate(record_number = row_number()) %>%
ungroup() %>%
complete(ID, record_number = 1:max(3, max(record_number))) %>%
filter(record_number <=3 | !is.na(subject))
#> # A tibble: 10 x 3
#> ID record_number subject
#> <dbl> <int> <chr>
#> 1 1 1 A1
#> 2 1 2 A2
#> 3 1 3 <NA>
#> 4 2 1 A1
#> 5 2 2 <NA>
#> 6 2 3 <NA>
#> 7 3 1 A1
#> 8 3 2 A2
#> 9 3 3 A3
#> 10 3 4 A4
由reprex package创建于2019年2月6日(v0.2.1)
将只使用基础R是一种方法
#Get number of rows for each ID and subtract it from min_row_id
#keep only those which we need to add
temp <- subset(aggregate(subject~ID, df, function(x) min_row_id - length(x)),
subject < min_row_id & subject > 0)
#Add those new rows and rbind the original dataframe
new_df <- rbind(df, do.call(rbind, mapply(function(x, y)
data.frame(ID = x, subject = rep(NA, y)),
temp$ID, temp$subject, SIMPLIFY = FALSE)))
#If needed order them according to ID
new_df[order(new_df$ID), ]
# ID subject
#1 1 A1
#2 1 A2
#8 1 <NA>
#3 2 A1
#9 2 <NA>
#10 2 <NA>
#4 3 A1
#5 3 A2
#6 3 A3
#7 3 A4
另base
替代。每个 'ID' 中使用tapply
到索引([
) '主体',从1到组max
和3(min_row_id)的length
。对超过基长度的索引时,相应的值是NA
。
通过rep
licating列表中的元素,以每个元素(lengths
)的长度的名称重新正确长度的“ID”。使用unlist
创建一个“主题”栏。
l <- tapply(d$subject, d$ID, function(x) x[1:(max(c(length(x), 3)))])
data.frame(id = rep(names(l), lengths(l)), subject = unlist(l, use.names = FALSE))
# id subject
# 1 1 A1
# 2 1 A2
# 3 1 <NA>
# 4 2 A1
# 5 2 <NA>
# 6 2 <NA>
# 7 3 A1
# 8 3 A2
# 9 3 A3
# 10 3 A4