首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用mean by group / subset替换NA?

如何用mean by group / subset替换NA?
EN

Stack Overflow用户
提问于 2012-02-17 12:10:17
回答 5查看 36.3K关注 0票数 20

我有一个数据框架,里面有蜥蜴内脏中各种节肢动物的长度和宽度。因为一些内脏有数千种特定的猎物,所以我只测量了每种猎物类型的一个子集。现在我想用猎物的平均长度和宽度替换每个未测量的个体。我想保留数据帧,只添加指定的列(length2、width2)。主要原因是,每一行也有列,其中包含收集火蜥蜴的日期和位置的数据。我可以用随机选择的被测量个体来填充NA,但为了便于讨论,让我们假设我只想用平均值替换每个NA。

例如,假设我有一个数据帧,如下所示:

代码语言:javascript
复制
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或编程,但我正在努力学习。

我不知道我在做什么,但如果有帮助的话,我会试着创建一个小的数据集。

代码语言:javascript
复制
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)))

下面是我尝试过的一些方法(没起作用):

代码语言:javascript
复制
# 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? 

另一次尝试:

代码语言:javascript
复制
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)) 
  })

有什么建议吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-02-17 12:38:16

这不是我自己的技术,我之前在黑板上看到过:

代码语言:javascript
复制
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方法:

代码语言:javascript
复制
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

代码语言:javascript
复制
library(data.table)
setDT(dat)

dat[, length := impute.mean(length), by = taxa][,
    width := impute.mean(width), by = taxa]

dplyr

代码语言:javascript
复制
library(dplyr)

dat %>%
    group_by(taxa) %>%
    mutate(
        length = impute.mean(length),
        width = impute.mean(width)  
    )
票数 45
EN

Stack Overflow用户

发布于 2019-10-28 22:50:54

其他几个选项:

1)采用的全新 nafill**-function**

代码语言:javascript
复制
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][]

带有 's na.aggregate**-function**的2)

代码语言:javascript
复制
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-parameter中指定该函数(例如:FUN = median)。另请参阅?na.aggregate的帮助文件。

当然,您也可以在tidyverse中使用以下内容:

代码语言:javascript
复制
library(dplyr)
library(zoo)

dat %>% 
  group_by(taxa) %>% 
  mutate_at(cols, na.aggregate)
票数 4
EN

Stack Overflow用户

发布于 2015-09-02 22:10:15

在回答这个问题之前,我想说我是R的初学者。因此,如果你觉得我的答案是错的,请告诉我。

代码:

代码语言:javascript
复制
DF[is.na(DF$length), "length"] <- mean(na.omit(telecom_original_1$length))

并对宽度应用相同的方法。

DF代表data.frame的名称。

谢谢,帕蒂

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9322773

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档