サンショウウオの腸からのさまざまな節足動物の長さと幅のデータフレームがあります。いくつかの内臓には何千もの特定の獲物アイテムがあったため、私は各獲物タイプのサブセットのみを測定しました。次に、測定されていない各個体を、その獲物の平均の長さと幅に置き換えます。データフレームを保持し、補完された列(length2、width2)を追加するだけです。主な理由は、各行にはサンショウウオが収集された日付と場所に関するデータを含む列があることです。 NAを測定された個人のランダムな選択で埋めることができますが、議論のために、各NAを平均で置き換えたいと仮定しましょう。
たとえば、次のようなデータフレームがあるとします。
id taxa length width
101 collembola 2.1 0.9
102 mite 0.9 0.7
103 mite 1.1 0.8
104 collembola NA NA
105 collembola 1.5 0.5
106 mite NA NA
実際には、より多くの列と約25の異なる分類群と合計で約30,000の獲物アイテムがあります。これにはplyrパッケージが理想的かもしれませんが、これを行う方法がわかりません。私はRやプログラミングに精通しているわけではありませんが、学びたいと思っています。
私が何をしているのかはわかりませんが、役立つ場合は、小さなデータセットを作成して遊んでみます。
exampleDF <- data.frame(id = seq(1:100), taxa = c(rep("collembola", 50), rep("mite", 25),
rep("ant", 25)), length = c(rnorm(40, 1, 0.5), rep("NA", 10), rnorm(20, 0.8, 0.1), rep("NA",
5), rnorm(20, 2.5, 0.5), rep("NA", 5)), width = c(rnorm(40, 0.5, 0.25), rep("NA", 10),
rnorm(20, 0.3, 0.01), rep("NA", 5), rnorm(20, 1, 0.1), rep("NA", 5)))
これが私が試したいくつかのことです(うまくいきませんでした):
# mean imputation to recode NA in length and width with means
(could do random imputation but unnecessary here)
mean.imp <- function(x) {
missing <- is.na(x)
n.missing <-sum(missing)
x.obs <-a[!missing]
imputed <- x
imputed[missing] <- mean(x.obs)
return (imputed)
}
mean.imp(exampleDF[exampleDF$taxa == "collembola", "length"])
n.taxa <- length(unique(exampleDF$taxa))
for(i in 1:n.taxa) {
mean.imp(exampleDF[exampleDF$taxa == unique(exampleDF$taxa[i]), "length"])
} # no way to get back into dataframe in proper places, try plyr?
別の試み:
imp.mean <- function(x) {
a <- mean(x, na.rm = TRUE)
return (ifelse (is.na(x) == TRUE , a, x))
} # tried but not sure how to use this in ddply
Diet2 <- ddply(exampleDF, .(taxa), transform, length2 = function(x) {
a <- mean(exampleDF$length, na.rm = TRUE)
return (ifelse (is.na(exampleDF$length) == TRUE , a, exampleDF$length))
})
助言がありますか?
私自身のテクニックではなく、しばらく前にボードで見ました:
dat <- read.table(text = "id taxa length width
101 collembola 2.1 0.9
102 mite 0.9 0.7
103 mite 1.1 0.8
104 collembola NA NA
105 collembola 1.5 0.5
106 mite NA NA", header=TRUE)
library(plyr)
impute.mean <- function(x) replace(x, is.na(x), mean(x, na.rm = TRUE))
dat2 <- ddply(dat, ~ taxa, transform, length = impute.mean(length),
width = impute.mean(width))
dat2[order(dat2$id), ] #plyr orders by group so we have to reorder
編集for
ループを使用する非層アプローチ:
for (i in which(sapply(dat, is.numeric))) {
for (j in which(is.na(dat[, i]))) {
dat[j, i] <- mean(dat[dat[, "taxa"] == dat[j, "taxa"], i], na.rm = TRUE)
}
}
編集多くの月は後でdata.table&dplyrアプローチ:
data.table
library(data.table)
setDT(dat)
dat[, length := impute.mean(length), by = taxa][,
width := impute.mean(width), by = taxa]
dplyr
library(dplyr)
dat %>%
group_by(taxa) %>%
mutate(
length = impute.mean(length),
width = impute.mean(width)
)
これに答える前に、Rの初心者だと言いたいので、私の答えが間違っていると思われる場合はお知らせください。
コード:
DF[is.na(DF$length), "length"] <- mean(na.omit(telecom_original_1$length))
幅にも同じように適用します。
DFはdata.frameの名前を表します。
ありがとう、Parthi
@Tyler Rinkerのソリューションを拡張して、features
が代入する列であるとします。この場合はfeatures <- c('length', 'width')
です。次に、data.table
ソリューションは次のようになります。
library(data.table)
setDT(dat)
dat[, (features) := lapply(.SD, impute.mean), by = taxa, .SDcols = features]
他のいくつかのオプション:
1) data.table の新しいnafill
- function
library(data.table)
setDT(dat)
cols <- c("length", "width")
dat[, (cols) := lapply(.SD, function(x) nafill(x, type = "const", fill = mean(x, na.rm = TRUE)))
, by = taxa
, .SDcols = cols][]
2) Zoo のna.aggregate
- functionを使用
library(Zoo)
library(data.table)
setDT(dat)
cols <- c("length", "width")
dat[, (cols) := lapply(.SD, na.aggregate)
, by = taxa
, .SDcols = cols][]
na.aggregate
のデフォルトの関数はmean
です。別の関数を使用する場合は、FUN
パラメータを使用して指定する必要があります(例:FUN = median
)。 ?na.aggregate
のヘルプファイルも参照してください。
もちろん、これをtidyverseで使用することもできます:
library(dplyr)
library(Zoo)
dat %>%
group_by(taxa) %>%
mutate_at(cols, na.aggregate)