簡體   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