2012-05-15 40 views
12

Tôi đang làm việc trên một tập dữ liệu bao gồm dữ liệu cộng đồng và nhiều cột (các loài) có rất nhiều số 0. Tôi muốn có thể thả các cột này cho một số phân tích tôi đang làm, dựa trên tổng của toàn bộ cột. Tôi bị cám dỗ để làm điều này với vòng lặp for, nhưng tôi biết rằng các hàm áp dụng và theo hàm sẽ tốt hơn khi bạn sử dụng R. Mục tiêu của tôi là xóa tất cả các cột có tổng số nhỏ hơn 15. Tôi có sử dụng which() để loại bỏ hàng bởi các yếu tố, ví dụ:Loại trừ các cột khỏi một khung dữ liệu dựa trên các khoản cột

September<-which(data$Time_point=="September") 

data<-data[-September,] 

và hai cách tôi đã cố gắng loại bỏ các cột là bằng cách sử dụng apply():

data<-data[,apply(data,2,function(x)sum(x<=15))] 

và bằng cách sử dụng một hỗn độn cho vòng/nếu kết hợp khác :

for (i in 6:length(data)){ 
    if (sum(data[,i])<=15) 
    data[,i]<-NULL 
    else 
    data[,i]<-data[,i] 
    } 

Cả hai phương pháp này đều không hoạt động. Chắc chắn có một cách thanh lịch để loại bỏ các cột dựa trên các tiêu chí hợp lý?

str(head(data,10)) 
'data.frame': 10 obs. of 23 variables: 
$ Core_num : Factor w/ 159 levels "152","153","154",..: 133 72 70 75 89 85 86 90 95 99 
$ Cage_num : num 0 1 2 3 4 5 6 7 8 9 
$ Treatment : Factor w/ 4 levels "","C","CC","NC": 1 2 2 2 2 2 2 2 2 2 
$ Site  : Factor w/ 10 levels "","B","B07","B08",..: 1 8 8 8 7 7 7 7 9 9 
$ Time_point : Factor w/ 3 levels "","May","September": 1 2 2 2 2 2 2 2 2 2 
$ Spionidae : num 108 0 0 0 0 0 0 0 0 0 
$ Syllidae : num 185 0 0 0 3 8 0 1 4 1 
$ Opheliidae : num 424 0 1 0 0 0 1 1 0 0 
$ Cossuridae : num 164 0 7 3 0 0 0 0 0 0 
$ Sternaspidae: num 214 0 0 6 1 0 11 9 0 0 
$ Sabellidae : num 1154 0 2 2 0 ... 
$ Capitellidae: num 256 1 10 17 0 3 0 0 0 0 
$ Dorvillidae : num 21 1 0 0 0 0 0 0 0 0 
$ Cirratulidae: num 17 0 0 0 0 0 0 0 0 0 
$ Oligochaeta : num 3747 12 41 27 32 ... 
$ Nematoda : num 410 5 4 13 0 0 0 2 2 0 
$ Sipuncula : num 33 0 0 0 0 0 0 0 0 0 
$ Ostracoda : num 335 0 1 0 0 0 0 0 0 0 
$ Decapoda : num 62 0 4 0 1 0 0 0 0 0 
$ Amphipoda : num 2789 75 17 34 89 ... 
$ Copepoda : num 75 0 0 0 0 0 0 0 0 0 
$ Tanaidacea : num 84 0 0 0 1 0 0 0 0 0 
$ Mollusca : int 55 0 4 0 0 0 0 0 0 0 
+1

Nó sẽ dễ dàng hơn nhiều để giúp đỡ nếu bạn cung cấp một số dữ liệu tái sản xuất. Ví dụ, đầu ra của 'str (đầu (dữ liệu, 10))' có thể là đủ. (Các phiên bản in của dữ liệu bạn thường vô dụng, vì chúng khó sao chép + dán vào ví dụ, và chúng không cung cấp thông tin về cách dữ liệu được _stored_, điều này có thể rất quan trọng.) – joran

+0

Cảm ơn @joran. Tôi đã chỉnh sửa câu hỏi gốc để chứa đầu ra đó. Xin lỗi vì sự bất tiện! – Margaret

Trả lời

13

Còn về một tập con đơn giản thì sao? Đầu tiên, chúng ta tạo ra một dữ liệu đơn giản frameL

R> dd = data.frame(x = runif(5), y = 20*runif(5), z=20*runif(5)) 

Sau đó chọn cột nơi tổng lớn hơn 15

R> dd1 = dd[,colSums(dd) > 15] 
R> ncol(dd1) 
[1] 2 

Trong bộ dữ liệu của bạn, bạn chỉ muốn tập hợp con các cột 6 trở đi, vì vậy cái gì đó như :

##Drop the first five columns 
dd[,colSums(dd[,6:ncol(dd)]) > 15] 

hoặc

#Keep the first six columns 
cols_to_drop = c(rep(TRUE, 5), dd[,6:ncol(dd)]>15) 
dd[,cols_to_drop] 

sẽ hoạt động.


Điều quan trọng cần lưu ý là trong dấu ngoặc vuông, chúng tôi muốn một vectơ lôgic, ví dụ: vectơ TRUE và FALSE. Vì vậy, nếu bạn muốn tập hợp con bằng cách sử dụng một cái gì đó phức tạp hơn một chút, sau đó tạo một hàm trả về TRUE hoặc FALSE và tập hợp con như bình thường.

3

Bạn sẽ có thể lập chỉ mục trực tiếp dữ liệu của mình.bạn có boolean và colSums().Ví dụ:

set.seed(123) 
dat <- data.frame(var1 = runif(10), var2 = rnorm(10), var3 = rlnorm(10)) 
colSums(dat) 
#----- 
    var1  var2  var3 
5.782475 1.317914 12.91987 
#Let's set the threshold at 5, so we should get var1 and var3 
> dat[, colSums(dat) > 5] 
#----- 
     var1  var3 
1 0.2875775 5.9709924 
2 0.7883051 1.6451811 
3 0.4089769 0.1399294 
... 

EDIT - để giải quyết các cột không phải số

set.seed(123) 
dat <- data.frame(var1 = runif(10), var2 = rnorm(10), var3 = rlnorm(10), var4 = "notNumeric") 

require(plyr) 
dat[, -which(numcolwise(sum)(dat) < 5)] 

Consolec:/Documents and Settings/charles/desktop/

> dat[, -which(numcolwise(sum)(dat) < 5)] 
     var1  var3  var4 
1 0.2875775 5.9709924 notNumeric 
2 0.7883051 1.6451811 notNumeric 
3 0.4089769 0.1399294 notNumeric 
..... 
+2

Cue OP nói rằng nó không hoạt động trên bộ dữ liệu của họ trong 3 ... 2 ... 1 ... (xem 6 cột đầu tiên của khung dữ liệu của họ). – joran

+0

'dữ liệu [, c (1: 5, colSums (dữ liệu [, 6: chiều dài (dữ liệu)]> 15])]'. Phiên bản áp dụng sẽ tương tự nhưng tôi nghĩ 'colSums' nhanh hơn. – Justin

+0

@joran - bah Nếu không suy nghĩ quá nhiều, điều này sẽ làm việc 'require (plyr); dat [, -which (numcolwise (sum (dat) Chase

1

này sẽ trả lại các cột không chứa tất cả các số không, kể cả các yếu tố và các cột ký tự (tôi chỉ đọc trong điều đầu tiên của dữ liệu của bạn):

đọc trong một số dữ liệu của bạn:

dat <- read.table(text=" Core_num Cage_num Treatment Site Time_point Spionidae Nereididae Syllidae Opheliidae 
6  24  1   C M2  May   0   0  0   0 
4  22  2   C M2  May   0   0  0   1 
9  27  3   C M2  May   0   0  0   0 
23  41  4   C M  May   0   0  3   0 
19  37  5   C M  May   0   0  8   0 
20  38  6   C M  May   0   0  0   1", header=T) 

Mã:

summer <- function(x){ 
    if(is.numeric(x)){ 
     sum(x) > 15 
    } else { 
     TRUE 
    } 
} 

dat[, sapply(dat, summer)] 
Các vấn đề liên quan