繁体   English   中英

根据唯一 ID 合并数据帧的行

[英]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 值的情况(例如,通过取两个值的平均值) .

在我的现实生活中,我还必须采取一些额外的步骤,但这个例子的简单性并没有体现出来,包括:

  1. 对 df 进行排序并重置索引,以便 df 中的条目位置在两个 df 中保持一致,如下所示:
df <- df[order(df$Name), ]
rownames(df) <- NULL 
  1. 检查每个名称是否恰好出现两次,不多也不少:
#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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM