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.

Nishanth
sumber

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)
Hadley
sumber
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
davechilders
sumber
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.

Konrad Rudolph
sumber
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)
bschneidr
sumber
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));
Anton Andreev
sumber
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()
davsjob
sumber