【问题标题】:How do I replace a portion of NA's in a column with the mean of a grouping variable?如何用分组变量的平均值替换列中的一部分 NA?
【发布时间】:2020-07-30 17:51:20
【问题描述】:

我有一个包含长度和大小变量的数据集。我找到了大小变量的平均长度; spat=29.5,small=59.35,market=97.0。我还发现每个尺寸分组的测量值比例 spat=11%、small=38% 和 market=50%。

我想根据上面给出的比例填写数据集中未测量的 (na) 长度,并根据上面给出的平均值为每个比例分配一个长度。

例如,11% 的 na 将被替换为 29.5 长度,38% 将被替换为 59.35,50% 将被替换为 97.0

有谁知道实现这项工作的代码吗?

如果我遗漏了什么,我很抱歉,这是我第一次提问。

     Length   size 
    NA        NA
    68         Small    
   NA         NA  
    84        Market    
    NA        NA  
    75        Small    
    81        Market    
    NA        NA   
     32        Spat    
     28        Spat    
     18        Spat    
      NA      NA   
      21       Spat    
      30       Spat    
      NA      NA  
           

【问题讨论】:

  • 请分享一点样本数据,~20 行就足够了。 dput() 是共享数据的最佳方式,因为它可以复制/粘贴,请尝试 dput(your_data[1:20, ])(或选择不同的子集,以便有足够的 NA 值使其成为一个很好的例子)。
  • 我尝试了 dput,但不确定这是否是您要查找的内容,但我已将数据编辑到原始帖子中
  • 这看起来很有希望,但缺少一点。 dput() 应该以 structure( 开头才能完全复制/粘贴。

标签: r replace na missing-data


【解决方案1】:

这有点长,但它应该可以完成工作。

sizes = unique(size)[!is.na(unique(size))]
props = c(1:length(sizes))
for (i in 1:length(sizes)) props[i] = length(Length[which(size == sizes[i])]) / length(Length[!is.na(Length)])
means = c(1:length(sizes))
for (i in 1:length(sizes)) means[i] = mean(Length[which(size == sizes[i])])

idx = round(cumsum(props) * sum(is.na(size)))
nass = c()
nals = c()
for (i in 1:length(idx)) nass = append(nass, rep(sizes[i], (idx[i] - length(nass))))
for (i in 1:length(idx)) nals = append(nals, rep(means[i], (idx[i] - length(nals))))
size[is.na(size)] = nass
Length[is.na(Length)] = nals

让我解释一下我在这里做什么。以下行将所有唯一大小放入一个数组中:

sizes = unique(size)[!is.na(unique(size))]

下面的循环计算大小不为空的比例。

props = c(1:length(sizes))
for (i in 1:length(sizes)) props[i] = length(Length[which(size == sizes[i])]) / length(Length[!is.na(Length)])

以下循环计算每个尺寸的均值。

means = c(1:length(sizes))
for (i in 1:length(sizes)) means[i] = mean(Length[which(size == sizes[i])])

以下行计算我们需要填充的缺失 (NA) 案例的数量与非缺失大小值成比例。

idx = round(cumsum(props) * sum(is.na(size)))

以下两个循环创建我们将输入到原始数据集的新值。

nass = c()
nals = c()
for (i in 1:length(idx)) nass = append(nass, rep(sizes[i], (idx[i] - length(nass))))
for (i in 1:length(idx)) nals = append(nals, rep(means[i], (idx[i] - length(nals))))

最后我们将这些新值粘贴到原始向量中(即大小和长度)

size[is.na(size)] = nass
Length[is.na(Length)] = nals

【讨论】:

  • 您好,您的代码运行良好,但现在我想知道如何调整它以执行完全相同的操作,按组获取长度比例(不同的变量)。因此,每个特定组中的缺失值将由测量的牡蛎的比例填充。
  • 您可以更改变量名称。在此示例中,它们是“大小”和“长度”。只需更改这些名称即可对不同的变量执行相同的操作。
  • 我想你误会了我。分组没有缺失值,我想完全按照代码现在所做的那样做,但我不想没有特定的分组,而是希望每个样本都有它,以便缺失的变量在样本之间均匀分布
【解决方案2】:

以下函数可以满足问题的要求。
要分配的值的格式不清楚,我假设一个命名向量

结果是一个命名列表,其中成员 x(新值)和 groups(新组变量值)。

fill_perc <- function(x, groups, prob, values){
  stopifnot(length(prob) == length(values))
  prob <- prob/sum(prob)
  i <- which(is.na(x))
  j <- sample(length(values), size = length(i), prob = prob, replace = TRUE)
  x[i] <- values[j]
  groups[i] <- names(values)[j]
  list(x = x, groups = groups)
}

P <- c(11.8, 38, 50)
V <- setNames(c(29.5, 59.35, 97), c("Spat", "Small", "Market"))

set.seed(2020)
fill_perc(Length, size, P, V)
#$x
# [1]  81.00  66.00  44.00  59.35  29.00  24.00  68.00  97.00  92.00  21.00
#[11]  28.00  25.00  59.35  97.00  34.00  91.00  97.00  65.00  58.00 110.00
#[21]  52.00  48.00  96.00  95.00  54.00  40.00  98.00  63.00 138.00  30.00
#[31] 110.00
#
#$groups
# [1] "Market" "Small"  "Small"  "Small"  "Spat"   "Spat"   "Small"  "Market"
# [9] "Market" "Spat"   "Spat"   "Spat"   "Small"  "Market" "Spat"   "Market"
#[17] "Market" "Small"  "Small"  "Market" "Small"  "Small"  "Market" "Market"
#[25] "Small"  "Small"  "Market" "Small"  "Market" "Spat"   "Market"

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-01
    • 2019-02-03
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    • 2012-03-08
    • 2019-03-22
    • 2016-10-03
    相关资源
    最近更新 更多