2011-06-05 52 views
35

Tôi muốn đặt (lọc) một khung dữ liệu bằng cách chỉ định các hàng không (!) để giữ trong khung dữ liệu mới. Đây là một mẫu dataframe đơn giản:Tập dữ liệu con bằng nhiều điều kiện lô hàng hợp lý để xóa

data 
v1 v2 v3 v4 
a v d c 
a v d d 
b n p g 
b d d h  
c k d c  
c r p g 
d v d x 
d v d c 
e v d b 
e v d c 

Ví dụ, nếu một hàng cột v1 có một "b", "d" hoặc "e", tôi muốn thoát khỏi điều đó hàng quan sát, sản xuất cấu hình dữ liệu sau:

v1 v2 v3 v4 
a v d c 
a v d d 
c k d c  
c r p g 

Tôi đã thành công khi subsetting dựa trên một điều kiện tại một thời điểm. Ví dụ: tại đây tôi xóa các hàng có v1 chứa "b":

sub.data <- data[data[ , 1] != "b", ] 

Tuy nhiên, tôi có nhiều, nhiều điều kiện như vậy, vì vậy, không nên thực hiện từng điều kiện một. Tôi đã không thành công với những điều sau đây:

sub.data <- data[data[ , 1] != c("b", "d", "e") 

hoặc

sub.data <- subset(data, data[ , 1] != c("b", "d", "e")) 

Tôi đã thử một số thứ khác là tốt, như !%in%, nhưng điều đó dường như không tồn tại. Bất kỳ ý tưởng nào?

Trả lời

37

Các ! nên xung quanh bên ngoài của tuyên bố:

data[!(data$v1 %in% c("b", "d", "e")), ] 

    v1 v2 v3 v4 
1 a v d c 
2 a v d d 
5 c k d c 
6 c r p g 
44

Hãy thử điều này

subset(data, !(v1 %in% c("b","d","e"))) 
+0

Tốt và đơn giản, cảm ơn. Tôi không chắc giải pháp nào tôi thích hơn, cái này hay giải pháp do Andrie cung cấp. Cả hai đều dễ dàng và hiệu quả. Cả ba giải pháp đều làm việc cho tôi và tôi chưa bao giờ sử dụng 'which()' trước đây. Vì vậy, nó đã được tốt đẹp để được giới thiệu với chức năng đó. – Jota

+9

Nếu nó giúp bạn quyết định xem có sử dụng 'tập hợp con' hay '[', hãy xem cảnh báo trong trợ giúp cho '? Tập hợp con': *" Đây là một chức năng tiện lợi được dùng để tương tác. Đối với lập trình tốt hơn là sử dụng các hàm subsetting tiêu chuẩn như [, và đặc biệt việc đánh giá phi tiêu chuẩn của tập con đối số có thể có hậu quả không lường trước được. "* – Andrie

+0

@Andrie Cảm ơn bạn đã thêm làm rõ. – chl

3
my.df <- read.table(textConnection(" 
v1 v2 v3 v4 
a v d c 
a v d d 
b n p g 
b d d h  
c k d c  
c r p g 
d v d x 
d v d c 
e v d b 
e v d c"), header = TRUE) 

my.df[which(my.df$v1 != "b" & my.df$v1 != "d" & my.df$v1 != "e"), ] 

    v1 v2 v3 v4 
1 a v d c 
2 a v d d 
5 c k d c 
6 c r p g 
4

Câu trả lời này được nhiều hơn có nghĩa là để giải thích tại sao, không phải là cách. Toán tử '==' trong R được vector hóa theo cách tương tự như toán tử '+'. Nó phù hợp với các yếu tố của bất cứ điều gì là ở phía bên trái để các yếu tố của bất cứ điều gì là ở phía bên phải, cho mỗi yếu tố. Ví dụ:

> 1:3 == 1:3 
[1] TRUE TRUE TRUE 

Đây là thử nghiệm đầu tiên là 1==1 đó là TRUE, thứ hai và thứ ba 2==23==3. Chú ý rằng điều này trả về một FALSE trong các yếu tố đầu tiên và thứ hai vì thứ tự là sai:

> 3:1 == 1:3 
[1] FALSE TRUE FALSE 

Bây giờ nếu một đối tượng là nhỏ hơn sau đó các đối tượng khác thì đối tượng nhỏ được lặp đi lặp lại nhiều như nó cần thiết để phù hợp với lớn hơn vật. Nếu kích thước của đối tượng lớn hơn không phải là phép nhân kích thước của đối tượng nhỏ hơn, bạn sẽ nhận được cảnh báo rằng không phải tất cả các phần tử đều được lặp lại. Ví dụ:

> 1:2 == 1:3 
[1] TRUE TRUE FALSE 
Warning message: 
In 1:2 == 1:3 : 
    longer object length is not a multiple of shorter object length 

Đây là trận đấu đầu tiên là 1==1, sau đó 2==2, và cuối cùng 1==3 (FALSE) vì phía bên trái nhỏ hơn. Nếu một trong hai bên chỉ là một yếu tố sau đó được lặp đi lặp lại:

> 1:3 == 1 
[1] TRUE FALSE FALSE 

Nhà điều hành đúng để kiểm tra nếu một phần tử nằm trong một vector thực sự là '%in%' được vector hóa chỉ tới phần tử bên trái (đối với mỗi phần tử trong vector trái nó được kiểm tra nếu nó là một phần của bất kỳ đối tượng nào trong phần tử bên phải).

Hoặc, bạn có thể sử dụng '&' để kết hợp hai câu lệnh logic. '&' mất hai yếu tố và kiểm tra elementwise nếu cả hai đều là TRUE:

> 1:3 == 1 & 1:3 != 2 
[1] TRUE FALSE FALSE 
10

Bạn cũng có thể thực hiện điều này bằng cách phá vỡ mọi thứ lên thành câu lệnh lô gíc riêng biệt bằng cách bao gồm & để tách các báo cáo.

subset(my.df, my.df$v1 != "b" & my.df$v1 != "d" & my.df$v1 != "e") 

Đây không phải là thanh lịch và có nhiều mã hơn nhưng có thể dễ đọc hơn cho người dùng R mới hơn. Như đã chỉ ra trong một chú thích ở trên, subset là một chức năng "thuận tiện" được sử dụng tốt nhất khi làm việc tương tác.

+1

không nên là '|' thay vì '&'? –

+0

@BenBolker Nếu bạn thay đổi thành '|', bạn nhận được cùng một dữ liệu như đã được đưa vào. – Jota

+1

@ Frank Bạn có thể giải thích logic của '&' được ghép nối với '! =' Ở đây không? Giống như Ben, có vẻ như '|' nên được sử dụng, nhưng bạn nói đúng là nó không nên. Tôi đặc biệt bối rối về việc đặt nhiều cột theo cách đó. Ví dụ, sử dụng dữ liệu mẫu của Herman ở trên, để loại bỏ tất cả các trường hợp "b" từ v1 và tất cả "n" từ v2, tôi sẽ nghĩ rằng 'my.df [my.df $ v1! =" B "& my. df $ v2! = "n",] 'sẽ chỉ xóa các trường hợp đáp ứng cả hai tiêu chí đó (tức là chỉ có Hàng 3), chứ không phải là một trong các tiêu chí đó (nghĩa là cả Hàng 3 và Hàng 4). Trong thực tế, sử dụng '|' với '! =' Làm những gì tôi mong đợi '&' để làm, nhưng tôi không hiểu tại sao. – coip

5
data <- data[-which(data[,1] %in% c("b","d","e")),] 
+3

'-which' là ác và sẽ mang lại kết quả không mong muốn trong trường hợp không có giá trị nào trong vectơ khớp với trong vector nguồn. – A5C1D2H2I1M1N2O1R2T1

0
sub.data<-data[ data[,1] != "b" & data[,1] != "d" & data[,1] != "e" , ] 

Larger nhưng đơn giản để hiểu (tôi đoán) và có thể được sử dụng với nhiều cột, ngay cả với !is.na(data[,1]).

1

Và cũng

library(dplyr) 
data %>% filter(!v1 %in% c("b", "d", "e")) 

hoặc

data %>% filter(v1 != "b" & v1 != "d" & v1 != "e") 

hoặc

data %>% filter(v1 != "b", v1 != "d", v1 != "e") 

Kể từ khi các nhà điều hành & được ngụ ý bởi dấu phẩy.

Các vấn đề liên quan