2013-01-24 35 views
10

Tôi tiếp tục chạy vào điều này và tự hỏi liệu có một công việc dễ dàng hay không. Đối với một số trường hợp tôi thấy nó hợp lý hơn để suy nghĩ về Subsetting một ma trận trongĐặt một data.frame với ma trận số nguyên

N <- 12 
N.NA <- 6 
dat <- data.frame(V1=runif(N),V2=runif(N)) 
sel.mat <- matrix(c(sample(seq(N),N.NA),sample(ncol(dat),N.NA,replace=TRUE)),ncol=2) 

này hoạt động để lựa chọn, nhưng không phải để thay thế:

> dat[sel.mat] 
[1] 0.2582569 0.8455966 0.8828083 0.5384263 0.9574810 0.5623158 
> dat[sel.mat] <- NA 
Error in `[<-.data.frame`(`*tmp*`, sel.mat, value = NA) : 
    only logical matrix subscripts are allowed in replacement 

Tôi nhận ra rằng có một lý do cho thông báo lỗi (nó sẽ không biết phải làm gì nếu bạn có nhiều thay thế trỏ đến cùng một phần tử), nhưng điều đó không ngăn R cho phép thay thế số nguyên trên vectơ (ví dụ: dat$V1[c(2,3)] <- NA).

Có cách nào thuận tiện để cho phép thay thế bằng ma trận nguyên không?

+1

Trong ảnh chụp R-devel hiện tại, 'dat [sel.mat] <- na' ** được ** được hỗ trợ. Thay vào đó, việc lập chỉ mục ma trận với thay thế sẽ có sẵn từ R-3.0.0. (Xem câu trả lời của tôi bên dưới để biết thêm chi tiết.) –

Trả lời

2

FWIW, ma trận đánh chỉ có thay thế không làm việc trong ảnh chụp R-devel hiện tại (và sẽ là một phần của R-3.0.0). Rõ ràng một người nào đó trong R-core đã có cùng một mong muốn như bạn đã làm.

Theo tư liệu trong R-devel NEWS file:

Matrix lập chỉ mục của dataframes bởi chỉ số số hai cột hiện đang hỗ trợ cho việc thay thế cũng như khai thác.

Một cuộc biểu tình:

dat[sel.mat] 
## [1] 0.3355509 0.4114056 0.2334332 0.6597042 0.7707762 0.7783584 
dat[sel.mat] <- NA 
dat[sel.mat] 
## [1] NA NA NA NA NA NA 

R.version.string 
# [1] "R Under development (unstable) (2012-12-29 r61478)" 
+0

Thời gian thực sự giải quyết mọi vấn đề. –

+0

Vâng. Họ đã thêm mã vào tháng 10 năm 2012 và sẽ không đưa mã đó vào bản phát hành được đánh số cho đến tháng 4 năm 2013, nhưng tôi cho rằng đó là thử nghiệm beta tốt luôn như thế! –

0

Có thể sử dụng vòng lặp?

for (i in 1:nrow(sel.mat)) 
{ 
    dat[sel.mat[i,1],sel.mat[i,2]] <- NA 
} 

> dat 
       V1   V2 
    1   NA 0.27002155 
    2 0.7253383   NA 
    3   NA 0.63847293 
    4 0.1768720 0.64586587 
    5 0.3796935 0.62261843 
    6 0.6751365 0.78328647 
    7 0.9801140 0.82259732 
    8   NA 0.08606641 
    9 0.3294625 0.44110121 
    10 0.2830957   NA 
    11 0.6868594 0.09767882 
    12 0.9802349   NA 
7

Chuyển đổi nó vào một ma trận:

dat.m <- as.matrix(dat) 
dat.m[sel.mat] <- NA 
> dat.m 
      V1   V2 
[1,] 0.2539189   NA 
[2,] 0.5216975   NA 
[3,] 0.1206138 0.14714848 
[4,] 0.2841779 0.52352209 
[5,] 0.3965337   NA 
[6,] 0.1871074 0.23747235 
[7,] 0.2991774   NA 
[8,]  NA 0.09509202 
[9,] 0.4636460 0.59384430 
[10,] 0.5493738 0.92334630 
[11,] 0.7160894   NA 
[12,] 0.9568567 0.80398264 

Sửa giải thích tại sao chúng ta có một lỗi với data.frame

dat.m[sel.mat] <- NA 

tương đương với làm như sau:

temp <- dat 
dat <- "[<-"(temp, sel.mat, value=NA) 

Error in `[<-.data.frame`(temp, sel.mat, value = NA) : 
only logical matrix subscripts are allowed in replacement 

bây giờ tôi có thể làm các follwing và nó hoạt động:

dat <- "[<-"(as.matrix(temp), sel.mat, value=NA) 
6

Bạn có thể tạo ra một ma trận logic dựa trên ma trận số nguyên:

log.mat <- matrix(FALSE, nrow(dat), ncol(dat)) 
log.mat[sel.mat] <- TRUE 

ma trận này có thể được sử dụng để thay thế các giá trị trong khung dữ liệu với NA (hoặc giá trị khác):

is.na(dat) <- log.mat 

kết quả:

  V1   V2 
1 0.76063534   NA 
2 0.27713051 0.10593451 
3 0.74301263 0.77689458 
4 0.42202155   NA 
5 0.54563816 0.10233017 
6   NA 0.05818723 
7 0.83531963 0.93805113 
8 0.99316128 0.61505393 
9 0.08743757   NA 
10 0.95510231 0.51267338 
11 0.14035257   NA 
12 0.59408022   NA 

Điều này cho phép bạn giữ đối tượng gốc làm khung dữ liệu cho phép các cột thuộc các loại khác nhau.

2

Trong R, các từ ngữ

dat[sel.mat] 
dat[sel.mat] <- NA 

là phương pháp S3 và tương đương với

`[.data.frame`(x=dat, i=sel.mat) 
`[<-.data.frame`(x=dat, i=sel.mat, value=NA) 

từ class(dat) là "data.frame".

Bạn có thể nhìn vào mã nguồn của

`[.data.farme` 
`[<-.data.frame` 

và sửa đổi nó với những gì bạn muốn.


Trong trường hợp của bạn, có thể bạn muốn:

`[<-.data.frame` <- function(x, i, j, value) { 
    if (class(i) != "matrix") return(base:::`[<-.data.frame`(x, i, j, value)) 
    if (class(i[1]) != "integer") return(base:::`[<-.data.frame`(x, i, j, value)) 
    # check the length of i and value here 
    if (length(value) < nrow(i)) { 
    if (nrow(i) %% length(value) != 0) warning("some warning message should be here") 
    value <- rep(value, nrow(i) %/% length(value) + 1) 
    } 
    value <- value[1:nrow(i)] 
    for(index in 1:nrow(i)) { 
    x[i[index,1], i[index,2]] <- value[index] 
    } 
    return(x) 
} 

thử nó:

N <- 12 
N.NA <- 6 
dat <- data.frame(V1=runif(N),V2=runif(N)) 
sel.mat <- matrix(c(sample(seq(N),N.NA),sample(ncol(dat),N.NA,replace=TRUE)),ncol=2) 
dat[sel.mat] <- NA 
dat 
+0

(+1). Không chắc chắn lý do tại sao điều này đã không nhận được nhiều upvotes khác hơn là viết lại chức năng cơ bản thường là tốt nhất tránh để tránh nhầm lẫn. Nhưng đó là một lời giải thích tốt đẹp. –

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