2012-02-24 39 views
40

Tôi có ma trận (2601 x 58) ước tính nồng độ hạt từ mô hình chất lượng không khí. Bởi vì màn hình chất lượng không khí thực tế không thể đo lường dưới 0,1 ug/L, tôi cần phải thay thế tất cả các giá trị trong ma trận của tôi là <0.1 với giá trị bằng không/NA/null.Thay thế tất cả các giá trị trong ma trận <0.1 bằng 0

Ai đó đã đề xuất ifelse(test, true, false) với một tuyên bố hợp lý, nhưng khi tôi thử điều này, nó sẽ xóa mọi thứ.

+2

Câu hỏi về việc thay thế giá trị âm hoặc bằng 0 là câu hỏi thú vị. Bởi vì rất nhiều mô hình được xây dựng trên cơ sở nhật ký (y), tôi thường thay thế chúng bằng trung điểm giữa giới hạn dưới của bình thường và số không. (Có thể là câu hỏi phụ được đặt ra tốt nhất trên stats.exchange.) –

+0

@Dwin, +1 cho nhận xét đó. Tôi muốn thấy câu hỏi thứ hai, và đó là câu trả lời trên crossvalidated.com –

+0

đó là một nhận xét thú vị - tôi thấy những gì bạn đang nói ... Đối với ngữ cảnh, tôi đang sử dụng các giá trị này trong hồi quy với dữ liệu phòng cấp cứu (nghiên cứu dịch tễ học dân số). Lời giải thích tôi đã đưa ra vì sao thay thế <0.1 bằng 0 là chúng ta không muốn đánh giá quá cao hiệu ứng ... một cái gì đó cần làm với "không thổi phồng"? – mEvans

Trả lời

39

ifelse nên làm việc:

mat <- matrix(runif(100),ncol=5) 
mat <- ifelse(mat<0.1,NA,mat) 

Nhưng tôi sẽ chọn câu trả lời Harlan của hơn tôi.

mat[mat < 0.1] <- NA 
+0

Điều với ifelse là nó có vẻ biến ma trận của tôi thành một vector ... tôi có thể tái định hình nó thành ma trận bằng cách nào đó không? – mEvans

+1

@mEvans nó không dành cho tôi! nếu tôi dán mã của tôi, tôi lấy ma trận ra sau ... nhưng có, bạn luôn có thể chuyển đổi 'vectơ' thành' ma trận' bằng cách sử dụng 'ma trận (mat)'. Hãy xem tất cả các đối số tùy chọn cho 'ma trận'. Nhưng, như tôi đã nói trong câu trả lời của mình, tôi nghĩ câu trả lời của Harlan là tốt nhất bằng một cú sút dài. – Justin

56
X[X < .1] <- 0 

(hay NA, mặc dù 0 có vẻ thích hợp hơn trong trường hợp này.)

Ma trận chỉ là vector với kích thước, vì vậy bạn có thể đối xử với họ như một vector khi bạn gán cho họ. Trong trường hợp này, bạn đang tạo một vectơ boolean trên X chỉ ra các giá trị nhỏ, và nó gán phần bên tay phải cho mỗi phần tử TRUE.

+0

Bạn có thể thực hiện việc này chỉ với một số cột nhất định không? Nó thay thế các giá trị khác trong các cột khác (như ngày và giờ, vv) khi tôi chạy nó trên toàn bộ ma trận. – mEvans

+2

Đối với một tập hợp các cols, bạn có thể sử dụng: 'X [, c (1,3,5)] <- áp dụng (X [, c (1,3,5)], 2, hàm (x) ifelse (x <0,1, 0, x)) '(cho các cột 1, 3 và 5). – jbaums

+7

@mEvans: nếu bạn có các loại dữ liệu khác nhau trong các cột khác nhau, điều đó có nghĩa là bạn có thể có khung dữ liệu chứ không phải ma trận. Đây là những sinh vật khác nhau trong R, mặc dù nhiều hoạt động sẽ làm việc với cả hai. Bạn nên kiểm tra xem tập dữ liệu của bạn là gì trước khi thực hiện bất kỳ điều gì khác, vì điều đó có thể sẽ giúp bạn tiết kiệm rất nhiều đau sau này. –

1

Chỉ cần để cung cấp một (theo ý kiến ​​của tôi) thay thế thú vị:

Nếu bạn cần để kiểm soát các giá trị để họ không bao giờ nhỏ hơn một giá trị, bạn có thể sử dụng pmax:

set.seed(42) 
m <- matrix(rnorm(100),10) 

m <- pmax(m, 0) # clamp negative values to 0 

... Điều này không hoàn toàn hoạt động trong trường hợp của bạn mặc dù vì bạn muốn các giá trị < 0.1 trở thành 0.

1

Các phương thức tương đương khác:

let:

M=matrix(rnorm(10*10), 10, 10) 

brute force (giáo dục)

for (i in 1:nrow(M)) { 
    for (j in 1:ncol(M)) if (M[i,j]<0.1 & !is.na(M[i,j])) M[i,j]=NA 
    } 

Nếu có giá trị thiếu (NA) trong M, bỏ !is.na sẽ cung cấp cho các lỗi.

Một cách khác: sử dụng recode trong gói car:

library(car) 
recode(M, "lo:0.099999=NA") 

Không thể chỉ định một sự bất bình đẳng nghiêm ngặt ở đây, vì vậy đó là lý do tại sao có một loạt các 9. Đặt nhiều nines và nó biến thành 0,1. lo là sự tiện lợi của việc mã hóa, cung cấp giá trị tối thiểu (loại bỏ NA).

1

Một giải pháp data.frame:

if(!require(plyr)){ 
    install.packages("plyr")} 

rm.neg<-colwise(function(x){ 
    return(ifelse(x < 0.1, 0, x))}) 

rm.neg(data.frame(mat)) 

PS: mã cho rm.neg thể được trích xuất và đơn giản hóa như vậy là không cần một cuộc gọi đến plyr, được sử dụng để tạo ra các chức năng colwise.

1

Tôi nghĩ rằng bạn sẽ thấy rằng 'ifelse' không phải là một hoạt động vectơ (thực sự hoạt động như một vòng lặp), và vì vậy nó là các đơn hàng có cường độ chậm hơn so với véc tơ tương đương. R ưu tiên các hoạt động vectơ, đó là lý do tại sao áp dụng, ánh xạ, một cách dễ dàng là sét nhanh cho các phép tính nhất định.

Tập dữ liệu nhỏ, không phải vấn đề, nhưng nếu bạn có độ dài từ 100k trở lên, bạn có thể đi nấu một bữa tối nướng trước khi kết thúc theo bất kỳ phương pháp nào liên quan đến vòng lặp.

Mã bên dưới sẽ hoạt động.

Đối với vector

minvalue <- 0 
X[X < minvalue] <- minvalue 

Đối Dataframe hoặc Matrix.

minvalue <- 0 
n <- 10 #change to whatever. 
columns <- c(1:n) 
X[X[,columns] < minvalue,columns] <- minvalue 

Một phương pháp nhanh chóng, thông qua chức năng Pmax và Pmin, này mũ mục giữa 0 và 1 và bạn có thể đặt một ma trận hoặc dataframe như là đối số đầu tiên không có vấn đề.

ulbound <- function(v,MAX=1,MIN=0) pmin(MAX,pmax(MIN,v)) 
Các vấn đề liên quan