HOWTO · R
R 中按列刪除重複行
這篇文章演示瞭如何在 R 中按列刪除重複的行
本頁內容
若要在 R 資料框中為每個所選鍵保留一行,當您需要其他列時,請使用 dplyr 的 distinct() 並設定 .keep_all = TRUE。以下每種方法都會按照資料目前的順序保留最早的符合行,因此當另一個記錄應優先時,請先排序。這些範例使用一個具有 id、group 和 score 列的小型資料框。
使用 dplyr 套件的 distinct 函式按列刪除 R 中的重複行
當 id 定義了唯一記錄,且您希望結果包含每個原始列時,請使用 distinct(df, id, .keep_all = TRUE)。distinct() 會比較所選的鍵列,並為每個鍵值保留第一行。使用 .keep_all = TRUE 時,其他列會被帶入結果中,但不會影響兩行是否符合。若沒有該引數,結果僅包含所選的列。
對於複合鍵,請列出每一列:distinct(df, id, group, .keep_all = TRUE)。這樣,具有相同 id 但不同 group 值的行便會保持分離。下面的完整範例使用相同的範例資料,並展示了兩種鍵的選擇。它需要安裝 dplyr;其結果在下文中說明,且此範例不附帶執行時的輸出。
df <- data.frame(
id = c(1, 2, 2, 3, 3),
group = c("A", "A", "B", "A", "B"),
score = c(8, 5, 9, 4, 7)
)
if (requireNamespace("dplyr", quietly = TRUE)) {
unique_by_id <- dplyr::distinct(df, id, .keep_all = TRUE)
unique_by_pair <- dplyr::distinct(df, id, group, .keep_all = TRUE)
print(unique_by_id)
print(unique_by_pair)
} else {
cat("Install dplyr to run these distinct() examples.\n")
}
單一鍵的結果保留了 (1, A, 8)、(2, A, 5) 和 (3, A, 4)。複合鍵的結果保留了這些行以及 (2, B, 9) 和 (3, B, 7),因為每個 id 與 group 的配對都是唯一的。下面的另一個 Base R 範例會列印這兩個結果。
df <- data.frame(
id = c(1, 2, 2, 3, 3),
group = c("A", "A", "B", "A", "B"),
score = c(8, 5, 9, 4, 7)
)
unique_by_id <- df[!duplicated(df$id), ]
unique_by_pair <- df[!duplicated(df[c("id", "group")]), ]
cat("By id:\n")
cat(paste(unique_by_id$id, unique_by_id$group, unique_by_id$score, sep = ":"), sep = "\n")
cat("\nBy id and group:\n")
cat(paste(unique_by_pair$id, unique_by_pair$group, unique_by_pair$score, sep = ":"), sep = "\n")
By id:
1:A:8
2:A:5
3:A:4
By id and group:
1:A:8
2:A:5
2:B:9
3:A:4
3:B:7
在這裡,!duplicated(df$id) 標記了每個 id 後續出現的位置;將鍵列的資料框傳遞給 duplicated() 會對其組合應用相同的首次出現規則。兩種選擇都保留了每個所選行的所有列。
使用 group_by、filter 和 duplicated 函式按列刪除 R 中的重複行
對於單一全域 id 鍵,filter(!duplicated(id)) 會保留其首次出現。如果輸入可能已經分組,請先呼叫 ungroup(),以便 filter() 對整個資料評估重複檢查:
df %>% ungroup() %>% filter(!duplicated(id))
管道 %>% 將其左側的值作為第一個引數傳遞給其右側的函式。在 filter(!duplicated(id)) 之前按 id 分組不會刪除後面的行:在每個 id 群組內,該鍵是恆定的,因此 duplicated(id) 找不到後續出現。按另一列分組在 ID 可能在每個群組內獨立重複時非常有用;此時,duplicated(id) 會保留每個群組中每個 ID 的首次出現。對於單一全域鍵,未分組的運算式與上面的 Base R 選擇具有相同的首行行為。
例如,按 group 分組會在每個群組內分別應用相同的檢查:
df %>%
group_by(group) %>%
filter(!duplicated(id)) %>%
ungroup()
此管線按照目前的行順序,保留每個 group 內每個 id 的第一行。在範例資料中,每個 id 與 group 的配對僅出現一次,因此每一行都是其在群組內該 id 的首次出現,五個行全部保留;若再有一行重複同一群組中已出現過的 id,則會被丟棄。
使用 group_by 和 slice 函式按列刪除 R 中的重複行
dplyr 管線 df %>% group_by(id) %>% slice(1) %>% ungroup() 從每個 id 群組中選取位置 1。目前的行順序決定了哪個記錄排在第一位;slice(1) 不會自動選取最高分或最新記錄。在分組和切片之前,請按照您希望的偏好排列資料,然後在後續操作應將結果視為普通資料框時取消分組。
對於範例資料,此方法保留了與單一鍵的 distinct() 和 duplicated() 方法相同的行:ID 1、2 和 3 的第一行。當任務是選取唯一的鍵組合時,請使用 distinct();當按每個群組內的位置選取一行是更廣泛的分組工作流程的一部分時,請使用 slice(1)。這些 dplyr 運算式僅供說明,且需要 dplyr 套件;上面的 Base R 範例無需該依賴即可執行。