[英]Merging rows of dataframe based on unique ID
我有一个数据框,其中所有参与者的唯一主题 ID 重复两次。 下面的数据似乎包含一列,其中一个条目的值为 NA,其中一个条目有一个值的一列(尽管这不确定,我使用的方法应该考虑到这不是真的)。 这是一个例子:
Name <- c("Jon", "Jon", "Maria", "Maria", "Tina", "Tina", "dan", 'dan', 'wen', 'wen')
a <- c(1, 1, 2, 2, 3, 4, 4, 4, 5, 6)
b <- c(NA, 1, NA, 2, NA, 3, NA, 4, NA, 5)
c <- c(1, NA, 2, NA, 3, NA, 4, NA, 5, NA)
df <- data.frame(Name, a, b, c)
到目前为止,我想到的解决方案包括遍历所有唯一 ID(在上面的示例中为名称)并为每个条目制作单独的数据帧。 像这样的东西:
#Instantiate list of lists that will become dfs
firstdf <- c()
seconddf <- c()
#Loop through existing df by unique ID (Name) and create
# list containing values of 1 entry and list of the other
for (i in unique(df$Name)) {
innerlist1 <- c()
innerlist2 <- c()
for (x in c(1:length(df[df['Name'] == i]))) {
if (x%%2 == 1) {
# Takes one set of entries per ID
innerlist1 <- c(innerlist1, df[df['Name'] == i][x])
} else if (x%%2 == 0) {
# Takes other set of entries per ID
innerlist2 <- c(innerlist2, df[df['Name'] == i][x])
}
}
firstdf <- c(firstdf, list(innerlist1))
seconddf <- c(seconddf, list(innerlist2))
}
# Make dfs from lists
firstdf <- do.call(rbind.data.frame, firstdf)
names(firstdf) <- names(df)
seconddf <- do.call(rbind.data.frame, seconddf)
names(seconddf) <- names(df)
然后,我将继续使用合并之类的方法将 dfs 与by="Name"
结合起来。 我的原始数据集很大,这不是特别有效或优雅。 任何人都可以提出改进建议吗?
您可以通过排除NA
的组来保留第一个值:
library(dplyr)
df %>%
group_by(Name) %>%
summarise(a = first(stats::na.omit(a)),
b = first(stats::na.omit(b)),
c = first(stats::na.omit(c)))
# A tibble: 5 x 4
Name a b c
<chr> <dbl> <dbl> <dbl>
1 dan 4 4 4
2 Jon 1 1 1
3 Maria 2 2 2
4 Tina 3 3 3
5 wen 5 5 5
如果每个 ID 有多个非 NA 值,您可以将它们集中到toString
。 您可以使用以下代码:
library(dplyr)
df %>%
group_by(Name) %>%
summarise_all(funs(toString(na.omit(.))))
输出:
# A tibble: 5 × 4
Name a b c
<chr> <chr> <chr> <chr>
1 dan 4, 4 4 4
2 Jon 1, 1 1 1
3 Maria 2, 2 2 2
4 Tina 3, 4 3 3
5 wen 5, 6 5 5
顺便说一句,对于未来的读者,我最终做的是通过奇数/偶数索引获取每个 ID 的每个条目,并制作两个数据帧,如下所示:
firstdf <- df[seq_len(nrow(df))%%2 == 1, ]
seconddf <- df[seq_len(nrow(df))%%2 == 0, ]
在此之后,只需删除所有条目都是 NA 的列,然后合并 dfs,同时处理两个 dfs 在同一位置相应地具有非 NA 值的情况(例如,通过取两个值的平均值) .
在我的现实生活中,我还必须采取一些额外的步骤,但这个例子的简单性并没有体现出来,包括:
df <- df[order(df$Name), ]
rownames(df) <- NULL
#Using dplyr
library(dplyr)
df %>%
count(Name) %>%
filter(n!=2)
# Should return 0 rows
在条目多于或少于两个的情况下,我执行了以下操作:
more <- df %>%
count(name) %>%
filter(n>2)
df_more_than_two <- df[df$Name %in% more$Name]
# Change sign in filter function to < 2 for those with only one entry
然后我制作了三个数据框(那些有 1 个条目,那些有 2 个条目,还有那些有 3 个条目),但基本上执行了相同的步骤
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.