Xóa các hàng trùng lặp


152

Tôi đã đọc một CSVtập tin vào một data.frame. Một số hàng có cùng thành phần trong một trong các cột. Tôi muốn xóa các hàng trùng lặp trong cột đó. Ví dụ:

platform_external_dbus          202           16                     google        1
platform_external_dbus          202           16         space-ghost.verbum        1
platform_external_dbus          202           16                  localhost        1
platform_external_dbus          202           16          users.sourceforge        8
platform_external_dbus          202           16                    hughsie        1

Tôi chỉ muốn một trong những hàng này vì các hàng khác có cùng dữ liệu trong cột đầu tiên.


3
bạn muốn cái nào chỉ là người đầu tiên? nói cách khác: bạn muốn giữ googlehay localhosthay hughsie?
Anthony Damico

Nó không quan trọng đối với phần này trong phân tích thống kê của tôi. Tôi chỉ cố gắng liên quan đến tiêu đề dự án (cột đầu tiên), số lỗi (cột thứ hai) và số lượng tổ chức trên dự án (cột thứ ba).
dùng1897691

3
mát mẻ. ném các cột không cần thiết ra và sử dụng? độc đáo
Anthony Damico

Câu trả lời:


186

chỉ cần cách ly khung dữ liệu của bạn với các cột bạn cần, sau đó sử dụng hàm duy nhất: D

# in the above example, you only need the first three columns
deduped.data <- unique( yourdata[ , 1:3 ] )
# the fourth column no longer 'distinguishes' them, 
# so they're duplicates and thrown out.

1
Điều này có vẻ như nó sẽ hoạt động hoàn hảo. Bạn có thể vui lòng giải thích cho tôi những gì đang xảy ra với [,1:3]một phần của mã đó? Tôi mới biết về R, đó là lý do tại sao tôi hỏi những gì tôi chỉ có thể giả định là một câu hỏi rõ ràng.
dùng1897691

6
@ user1897691 đánh dấu là chính xác sau đó;) xem cái này và nếu bạn thích cái đó, hãy kiểm tra twotorials.com
Anthony Damico

3
Xin lưu ý rằng điều này sẽ loại bỏ tất cả các cột ngoại trừ ba cột đầu tiên.
GuillaumeL

186

Đối với những người đã đến đây để tìm câu trả lời chung cho việc xóa hàng trùng lặp, hãy sử dụng !duplicated():

a <- c(rep("A", 3), rep("B", 3), rep("C",2))
b <- c(1,1,2,4,1,1,2,2)
df <-data.frame(a,b)

duplicated(df)
[1] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE

> df[duplicated(df), ]
  a b
2 A 1
6 B 1
8 C 2

> df[!duplicated(df), ]
  a b
1 A 1
3 A 2
4 B 4
5 B 1
7 C 2

Trả lời từ: Xóa các hàng trùng lặp khỏi khung dữ liệu R


Tôi muốn tạo một varibale mới gắn cờ nếu có một bản sao trên một biến nhất định gần giống như df $ trùng lặp <- ifelse (giá trị hàng này trong cột a == giá trị hàng trước đó trong cột a, 1, 0)
jacob

@jacob xem câu hỏi này stackoverflow.com/questions/12495345/ từ
dpel

2
Điều này giữ giá trị xuất hiện đầu tiên và loại bỏ phần còn lại của các bản sao, phải không? Hoặc nó loại bỏ các giá trị ngẫu nhiên?
News_is_Selection_Bias

@alph.usagamma vâng, nó giữ giá trị xuất hiện đầu tiên
Mehdi Nellen

2
Nếu bạn chỉ quan tâm đến các bản sao trong các cột nhất định, giả sử cols 1 và 2, chúng ta có thể sử dụngdf[!duplicated(df[, 1:2])]
qwr

82

Hàm distinct()trong dplyrgói thực hiện loại bỏ trùng lặp tùy ý, từ các cột / biến cụ thể (như trong câu hỏi này) hoặc xem xét tất cả các cột / biến. dplyrlà một phần của tidyverse.

Dữ liệu và gói

library(dplyr)
dat <- data.frame(a = rep(c(1,2),4), b = rep(LETTERS[1:4],2))

Xóa các hàng trùng lặp trong một cột cụ thể (ví dụ: cột a)

Lưu ý rằng .keep_all = TRUEgiữ lại tất cả các cột, nếu không thì chỉ agiữ lại cột .

distinct(dat, a, .keep_all = TRUE)

  a b
1 1 A
2 2 B

Xóa các hàng trùng lặp hoàn toàn của các hàng khác:

distinct(dat)

  a b
1 1 A
2 2 B
3 1 C
4 2 D

Great câu trả lời, bằng cách này, .keep_alllà cho dù để giữ tất cả các cột, không được trộn với keeptrong pandas.
Jason Goal

28

Các data.tablegói cũng có uniqueduplicated phương pháp của nó sở hữu với một số tính năng bổ sung.

Cả hai unique.data.tablevà các duplicated.data.tablephương thức đều có một byđối số bổ sung cho phép bạn chuyển một characterhoặc một integervectơ tên cột hoặc vị trí của chúng tương ứng

library(data.table)
DT <- data.table(id = c(1,1,1,2,2,2),
                 val = c(10,20,30,10,20,30))

unique(DT, by = "id")
#    id val
# 1:  1  10
# 2:  2  10

duplicated(DT, by = "id")
# [1] FALSE  TRUE  TRUE FALSE  TRUE  TRUE

Một tính năng quan trọng khác của các phương thức này là tăng hiệu suất rất lớn cho các tập dữ liệu lớn hơn

library(microbenchmark)
library(data.table)
set.seed(123)
DF <- as.data.frame(matrix(sample(1e8, 1e5, replace = TRUE), ncol = 10))
DT <- copy(DF)
setDT(DT)

microbenchmark(unique(DF), unique(DT))
# Unit: microseconds
#       expr       min         lq      mean    median        uq       max neval cld
# unique(DF) 44708.230 48981.8445 53062.536 51573.276 52844.591 107032.18   100   b
# unique(DT)   746.855   776.6145  2201.657   864.932   919.489  55986.88   100  a 


microbenchmark(duplicated(DF), duplicated(DT))
# Unit: microseconds
#           expr       min         lq       mean     median        uq        max neval cld
# duplicated(DF) 43786.662 44418.8005 46684.0602 44925.0230 46802.398 109550.170   100   b
# duplicated(DT)   551.982   558.2215   851.0246   639.9795   663.658   5805.243   100  a 

7

Bạn cũng có thể sử dụng dplyr's distinct()chức năng! Nó có xu hướng hiệu quả hơn các lựa chọn thay thế, đặc biệt nếu bạn có vô số quan sát.

distinct_data <- dplyr::distinct(yourdata)

1
Đây là câu trả lời giống như câu trả lời của Sam Firke, nhưng ít chi tiết hơn.
qwr

6

câu trả lời chung có thể là ví dụ:

df <-  data.frame(rbind(c(2,9,6),c(4,6,7),c(4,6,7),c(4,6,7),c(2,9,6))))



new_df <- df[-which(duplicated(df)), ]

đầu ra:

      X1 X2 X3
    1  2  9  6
    2  4  6  7

1
Hãy thận trọng khi sử dụng -which, điều này sẽ dẫn đến lỗi nếu không có trùng lặp, sử dụng df[!(duplicated(df)), ]có thể an toàn hơn.
Mục tiêu Jason

5

Với sqldf:

# Example by Mehdi Nellen
a <- c(rep("A", 3), rep("B", 3), rep("C",2))
b <- c(1,1,2,4,1,1,2,2)
df <-data.frame(a,b)

Giải pháp:

 library(sqldf)
    sqldf('SELECT DISTINCT * FROM df')

Đầu ra:

  a b
1 A 1
2 A 2
3 B 4
4 B 1
5 C 2

Điều này có chi phí thiết lập toàn bộ cơ sở dữ liệu SQL. cran.r-project.org/web/packages/sqldf/index.html
qwr 29/11/18

Bạn có ý nghĩa gì khi thiết lập toàn bộ cơ sở dữ liệu SQL? Đó là một trong những lợi thế chính: 'với sqldf, người dùng được giải phóng khỏi việc phải làm như sau, tất cả đều được thực hiện tự động: thiết lập cơ sở dữ liệu, viết câu lệnh tạo bảng xác định từng bảng, nhập và xuất vào và từ cơ sở dữ liệu '. Nó không phải là một giải pháp tối ưu, nhưng tiện dụng cho những người quen thuộc với SQL.
mpalanco

3

Hoặc bạn có thể lồng dữ liệu trong cols 4 và 5 thành một hàng với tidyr:

library(tidyr)
df %>% nest(V4:V5)

# A tibble: 1 × 4
#                      V1    V2    V3             data
#                  <fctr> <int> <int>           <list>
#1 platform_external_dbus   202    16 <tibble [5 × 2]>

Các bản sao col 2 và 3 hiện đã bị xóa để phân tích thống kê, nhưng bạn đã giữ dữ liệu col 4 và 5 trong một tibble và có thể quay lại khung dữ liệu gốc tại bất kỳ thời điểm nào unnest().


1

Xóa các hàng trùng lặp của một khung dữ liệu

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe
distinct(mydata)

Trong tập dữ liệu này, không có một hàng trùng lặp duy nhất nên nó trả về cùng số lượng hàng như trong mydata.



Xóa các hàng trùng lặp dựa trên một biến

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using carb variable
distinct(mydata,carb, .keep_all= TRUE)

Hàm .keep_all được sử dụng để giữ lại tất cả các biến khác trong khung dữ liệu đầu ra.



Xóa hàng trùng lặp dựa trên nhiều biến

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using cyl and vs variables
distinct(mydata, cyl,vs, .keep_all= TRUE)

Hàm .keep_all được sử dụng để giữ lại tất cả các biến khác trong khung dữ liệu đầu ra.

(từ: http://www.datasciencemadesimple.com/remove-dsplate-rows-r-USE-dplyr-distotype-feft/ )


0

Vấn đề này cũng có thể được giải quyết bằng cách chọn hàng đầu tiên từ mỗi nhóm trong đó nhóm là các cột dựa trên đó chúng tôi muốn chọn các giá trị duy nhất (trong ví dụ được chia sẻ, đây chỉ là cột thứ 1).

Sử dụng cơ sở R:

subset(df, ave(V2, V1, FUN = seq_along) == 1)

#                      V1  V2 V3     V4 V5
#1 platform_external_dbus 202 16 google  1

Trong dplyr

library(dplyr)
df %>% group_by(V1) %>% slice(1L)

Hoặc sử dụng data.table

library(data.table)
setDT(df)[, .SD[1L], by = V1]

Nếu chúng ta cần tìm ra các hàng duy nhất dựa trên nhiều cột, chỉ cần thêm các tên cột đó trong phần nhóm cho mỗi câu trả lời ở trên.

dữ liệu

df <- structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L), 
.Label = "platform_external_dbus", class = "factor"), 
V2 = c(202L, 202L, 202L, 202L, 202L), V3 = c(16L, 16L, 16L, 
16L, 16L), V4 = structure(c(1L, 4L, 3L, 5L, 2L), .Label = c("google", 
"hughsie", "localhost", "space-ghost.verbum", "users.sourceforge"
), class = "factor"), V5 = c(1L, 1L, 1L, 8L, 1L)), class = "data.frame", 
row.names = c(NA, -5L))

0

Dưới đây là một rất đơn giản, nhanh chóng dplyr/ tidygiải pháp:

Xóa các hàng hoàn toàn giống nhau:

library(dplyr)
iris %>% 
  distinct(.keep_all = TRUE)

Xóa các hàng giống nhau chỉ trong các cột nhất định:

iris %>% 
  distinct(Sepal.Length, Sepal.Width, .keep_all = TRUE)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.