2013-01-24 11 views
10

Ciągle w to wchodzę i zastanawiam się, czy nie ma łatwego obejścia. W niektórych sytuacjach, uważam, że bardziej logiczne, aby myśleć o podzbiorów matrycę wPodział elementu data.frame na macierz całkowitą

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) 

Działa to do wyboru, ale nie do zastąpienia:

> 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 

Zdaję sobie sprawę, że istnieje powód, dla komunikatu o błędzie (nie wiedziałby, co zrobić, gdybyś miał wiele zamienników wskazujących na ten sam element), ale to nie powstrzyma R przed dopuszczeniem zastępowania liczb całkowitych wektorami (np. dat$V1[c(2,3)] <- NA).

Czy istnieje wygodny sposób na zastąpienie przez macierz całkowitą?

+1

W obecnym R woju zrzutu 'DAT [sel.mat] <- NA' ** ** jest obsługiwany. Indeksowanie macierzy z zamiennikiem będzie dostępne w wersji R-3.0.0. (Zobacz moją odpowiedź poniżej po więcej szczegółów.) –

Odpowiedz

2

FWIW, indeksowania matrycy z wymianą działa w bieżącym R-devel migawki (i będzie być częścią R-3.0.0). Oczywiście ktoś w R-core miał takie samo życzenie jak ty.

Jak udokumentowano w R-devel NEWS file:

Matrix indeksowanie dataframes przez dwie kolumny wskaźników liczbowych jest obecnie obsługiwana przez zastąpienie jak i ekstrakcji.

Wykazanie:

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

Czas naprawdę rozwiązuje wszystkie problemy. –

+0

Tak. Dodali kod w październiku 2012 r., A nie będzie go w wydaniu numerowanym do kwietnia 2013 r., Ale przypuszczam, że tak właśnie wygląda dobre beta testy! –

0

Może za pomocą pętli?

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

przekonwertować go do macierzy:

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 

Edit wyjaśnić, dlaczego mamy błąd z data.frame

dat.m[sel.mat] <- NA 

jest równoważna wykonaj następujące czynności:

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 

teraz mogę zrobić follwing i to działa:

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

Można by stworzyć logiczną matrycę opartą na matrycy integer:

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

Macierz ta może być wykorzystywane do zastąpienia wartości w ramce danych z NA (lub inne wartości):

is.na(dat) <- log.mat 

rezultatem

  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 

Pozwala to zachować oryginalny obiekt jako ramkę danych umożliwiającą kolumny różnych typów.

2

W R, wyrażenia

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

sposoby S3 równoważne

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

od class(dat) jest "data.frame".

może zajrzeć do kodu źródłowego

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

i zmodyfikować go do tego, co chcesz.


W twoim przypadku, może chcesz:

`[<-.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) 
} 

spróbować:

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). Nie wiadomo, dlaczego nie udało się uzyskać większej liczby zmian, niż przepisywanie podstawowych funkcji, najlepiej jest unikać, aby uniknąć nieporozumień. Ale to miłe wyjaśnienie. –

Powiązane problemy