Подмножество data.frame с целочисленной матрицей
Я продолжаю сталкиваться с этим, и мне интересно, есть ли там легкая работа. В некоторых ситуациях я считаю логичнее думать о подмножестве матрицы в
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]
[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
Я понимаю, что есть причина для сообщения об ошибке (он не знал, что делать, если у вас было несколько заметок, указывающих на один и тот же элемент), но это не останавливает R от возможности целочисленной замены на векторах (например, dat$V1[c(2,3)] <- NA
).
Есть ли удобный способ разрешить замену целой матрицей?
Ответы
Ответ 1
FWIW, индексирование матрицы с заменой работает в текущем моментальном снимке R-devel
(и будет частью R-3.0.0
). Очевидно, кто-то из R-core имел такое же желание, как и вы.
Как описано в файле новостей R-devel:
Матричная индексация числовых кадров с помощью двухколонных числовых индексов теперь поддерживается как для замены, так и для извлечения.
Демонстрация:
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)"
Ответ 2
Преобразуйте его в матрицу:
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
Изменить объясните, почему у нас есть ошибка с data.frame
dat.m[sel.mat] <- NA
эквивалентно выполнению следующего:
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
теперь я могу сделать follwing, и он работает:
dat <- "[<-"(as.matrix(temp), sel.mat, value=NA)
Ответ 3
Вы можете создать логическую матрицу на основе целочисленной матрицы:
log.mat <- matrix(FALSE, nrow(dat), ncol(dat))
log.mat[sel.mat] <- TRUE
Эта матрица может использоваться для замены значений в кадре данных с помощью NA
(или других значений):
is.na(dat) <- log.mat
Результат:
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
Это позволяет сохранить исходный объект в виде кадра данных, позволяющего использовать столбцы разных типов.
Ответ 4
В R выражения
dat[sel.mat]
dat[sel.mat] <- NA
являются методами S3 и эквивалентны
`[.data.frame`(x=dat, i=sel.mat)
`[<-.data.frame`(x=dat, i=sel.mat, value=NA)
так как class(dat)
является "data.frame".
Вы можете посмотреть исходный код
`[.data.farme`
`[<-.data.frame`
и измените его на то, что вы хотите.
В вашем случае, возможно, вы хотите:
`[<-.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)
}
попробуйте:
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
Ответ 5
Возможно, используя цикл?
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