Hapus baris yang digandakan menggunakan dplyr


128

Saya memiliki data.frame seperti ini -

set.seed(123)
df = data.frame(x=sample(0:1,10,replace=T),y=sample(0:1,10,replace=T),z=1:10)
> df
   x y  z
1  0 1  1
2  1 0  2
3  0 1  3
4  1 1  4
5  1 0  5
6  0 1  6
7  1 0  7
8  1 0  8
9  1 0  9
10 0 1 10

Saya ingin menghapus duplikat baris berdasarkan dua kolom pertama. Output yang diharapkan -

df[!duplicated(df[,1:2]),]
  x y z
1 0 1 1
2 1 0 2
4 1 1 4

Saya secara khusus mencari solusi menggunakan dplyrpaket.

Jawaban:


137

Catatan : dplyrsekarang berisi distinctfungsi untuk tujuan ini.

Jawaban asli di bawah:


library(dplyr)
set.seed(123)
df <- data.frame(
  x = sample(0:1, 10, replace = T),
  y = sample(0:1, 10, replace = T),
  z = 1:10
)

Satu pendekatan adalah mengelompokkan, dan kemudian hanya mempertahankan baris pertama:

df %>% group_by(x, y) %>% filter(row_number(z) == 1)

## Source: local data frame [3 x 3]
## Groups: x, y
## 
##   x y z
## 1 0 1 1
## 2 1 0 2
## 3 1 1 4

(Dalam dplyr 0.2 Anda tidak memerlukan zvariabel dummy dan hanya akan bisa menulis row_number() == 1)

Saya juga sudah berpikir tentang menambahkan slice()fungsi yang akan berfungsi seperti:

df %>% group_by(x, y) %>% slice(from = 1, to = 1)

Atau mungkin variasi unique()yang memungkinkan Anda memilih variabel mana yang akan digunakan:

df %>% unique(x, y)

4
@dotcomken Sampai saat itu juga bisa menggunakandf %>% group_by(x, y) %>% do(head(.,1))
Holger Brandl

16
@ MahbubulMajumder itu akan bekerja, tetapi cukup lambat. dplyr 0.3 akandistinct()
Hadley

3
@adley Saya suka fungsi unik () dan berbeda (), namun, mereka semua menghapus duplikat ke-2 dari bingkai data. bagaimana jika saya ingin semua pertemuan pertama dari nilai duplikat dihapus? Bagaimana ini bisa dilakukan? Terima kasih atas bantuannya!
FlyingDutch

2
@MvZB - tidakkah Anda hanya mengatur (desc ()) dan kemudian menggunakan berbeda
Woodstock

Saya yakin ada solusi sederhana tetapi bagaimana jika saya ingin menyingkirkan kedua baris duplikat? Saya sering bekerja dengan metadata yang terkait dengan sampel biologis dan jika saya memiliki ID sampel duplikat, saya sering tidak dapat memastikan baris mana yang memiliki data yang benar. Taruhan paling aman adalah membuang keduanya untuk menghindari asosiasi metadata yang salah. Adakah solusi mudah selain membuat daftar sampel ID duplikat dan menyaring baris dengan ID tersebut?
glongo_fishes

191

Berikut ini adalah solusi menggunakan dplyr >= 0.5.

library(dplyr)
set.seed(123)
df <- data.frame(
  x = sample(0:1, 10, replace = T),
  y = sample(0:1, 10, replace = T),
  z = 1:10
)

> df %>% distinct(x, y, .keep_all = TRUE)
    x y z
  1 0 1 1
  2 1 0 2
  3 1 1 4

3
Solusi ini tampaknya jauh lebih cepat (10 kali dalam kasus saya) daripada yang disediakan oleh Hadley.
Calimo

101
Secara teknis ini juga merupakan solusi yang disediakan oleh Hadley :-)
Tyler Rinker

27

Demi kelengkapan, berikut ini juga berfungsi:

df %>% group_by(x) %>% filter (! duplicated(y))

Namun, saya lebih suka menggunakan solusi distinct, dan saya curiga ini lebih cepat juga.


7

Sebagian besar waktu, solusi terbaik adalah menggunakan distinct() dari dplyr, seperti yang telah disarankan.

Namun, inilah pendekatan lain yang menggunakan slice()fungsi dari dplyr.

# Generate fake data for the example
  library(dplyr)
  set.seed(123)
  df <- data.frame(
    x = sample(0:1, 10, replace = T),
    y = sample(0:1, 10, replace = T),
    z = 1:10
  )

# In each group of rows formed by combinations of x and y
# retain only the first row

    df %>%
      group_by(x, y) %>%
      slice(1)

Perbedaan menggunakan distinct() fungsi

Kelebihan dari solusi ini adalah ia membuatnya eksplisit baris mana yang dipertahankan dari kerangka data asli, dan dapat dipasangkan dengan baik dengan arrange()fungsinya.

Katakanlah Anda memiliki data penjualan pelanggan dan Anda ingin menyimpan satu catatan per pelanggan, dan Anda ingin catatan itu menjadi yang dari pembelian terakhir mereka. Maka Anda bisa menulis:

customer_purchase_data %>%
   arrange(desc(Purchase_Date)) %>%
   group_by(Customer_ID) %>%
   slice(1)

3

Saat memilih kolom dalam R untuk kumpulan data yang diperkecil, Anda sering kali bisa mendapatkan duplikat.

Dua baris ini memberikan hasil yang sama. Setiap menghasilkan set data unik dengan dua kolom yang dipilih saja:

distinct(mtcars, cyl, hp);

summarise(group_by(mtcars, cyl, hp));

1

Jika Anda ingin menemukan baris yang digandakan, Anda dapat menggunakan find_duplicatesdari hablar:

library(dplyr)
library(hablar)

df <- tibble(a = c(1, 2, 2, 4),
             b = c(5, 2, 2, 8))

df %>% find_duplicates()
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.