2012-02-17 53 views
12

我有一个数据帧,其中包含来自蝾螈胆量的各种节肢动物的长度和宽度。因为有些胆量有成千上万的猎物,我只测量了每种猎物类型的一个子集。我现在想用每个未测量的个体替换那个猎物的平均长度和宽度。我想保留数据框并只添加估算列(length2,width2)。主要原因是每行也有列有收集蝾螈的日期和地点的数据。我可以随机选择一个被测量的个体来填充NA,但为了论证的缘故,我们假设我只想用平均值替换每个NA。如何用R的子集中的平均值替换NA(用plyr?估算)

例如想象我有一个数据帧,看起来像:

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不同的类群和总总〜30000个猎物的。这似乎是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)) 
    }) 

任何建议使用plyr与否?

+7

您应该考虑用于计算值的包*鼠标*。 – 2012-02-17 04:51:24

+1

'mi'包装也相当不错。 'Amelia'比'mice'或'mi'快得多,但它确实依赖于你的变量是多元正态的 – richiemorrisroe 2012-02-17 09:19:40

回答

37

不是我自己的技术,我看到了它的篮板而回:

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环路非plyr方法:

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 ap proach:

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) 
    ) 
+3

@djhocking谢谢Hadley我发现了我偷了它的地方:[(LINK)](http:// www.mail-archive.com/[email protected]/msg58289.html) – 2012-02-17 05:35:16

2

前回答这个问题,我想说的是,我在河初学者因此,请让我知道如果你觉得我的回答是错误的。

代码:

DF[is.na(DF$length), "length"] <- mean(na.omit(telecom_original_1$length)) 

并应用相同的用于宽度。

DF代表data.frame的名称。

感谢, Parthi

0

扩展在@Tyler林克的解决方案,假设features都归咎于列。在这种情况下features <- c('length', 'width')。然后使用data.table解决方案变为:

library(data.table) 
setDT(dat) 

dat[, (features) := lapply(.SD, impute.mean), by = taxa, .SDcols = features]