【问题标题】:Replacing NAs with values from same column given conditional on match of third column根据第三列的匹配条件,用同一列中的值替换 NA
【发布时间】:2025-08-05 08:35:02
【问题描述】:

我需要用给定列的不同行的非 NA 值替换每一行的 NA。

在 var2 列中,名称之间没有唯一值。即,可能有一个跨 id 共享的 var2 值。

name<- rep(c("yygy","gryh","glqy","abye"),4)
var2<- c(101,102,102,104,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA)
data.frame(name,var2)



     name var2
  1  yygy  101
  2  gryh  102
  3  glqy  102
  4  abye  104
  5  yygy   NA
  6  gryh   NA
  7  glqy   NA
  8  abye   NA
  9  yygy   NA
  10 gryh   NA
  11 glqy   NA
  12 abye   NA
  13 yygy   NA
  14 gryh   NA
  15 glqy   NA
  16 abye   NA

基本上在上面的示例中,我希望在所有匹配的名称值中重复 var2 值,即对于 yygy 将有四行,每行有 101。

我在想一个来自 dplyr 的 join 函数可以工作,但不能完全实现。当然,这可以通过循环来完成,但理想情况下是寻找 tidyr/dplyr 方法或应用?

【问题讨论】:

    标签: r dplyr apply tidyr


    【解决方案1】:

    你可以使用tidyr::fill():

    library(tidyr)
    library(dplyr)
    
    df %>% 
      group_by(name) %>% 
      fill(var2)
    
    # A tibble: 16 x 2
    # Groups:   name [4]
    name  var2
    <fctr> <dbl>
    1   abye   104
    2   abye   104
    3   abye   104
    4   abye   104
    5   glqy   102
    6   glqy   102
    7   glqy   102
    8   glqy   102
    9   gryh   102
    10   gryh   102
    11   gryh   102
    12   gryh   102
    13   yygy   101
    14   yygy   101
    15   yygy   101
    16   yygy   101
    

    【讨论】:

    • 谢谢。我正在查看帮助文件,它指出它用以前的条目填充了行。所以我猜它起作用的原因是 group_by 按名称对 df 进行排序......如果有一个名称的值全部丢失怎么办?这不会把它扔掉,因为它会从以前的名字中获取价值吗?
    • 如果名称 'glqy' 在 var2 中最初是 NA 而不是 '102',那么在使用 fill() 命令后,所有值将保持为 NA。它不会使用名称“abye”中的值。
    • 啊,好可爱。谢谢!。有没有办法保持订单或恢复原来的订单?
    • 我不认为有一个简单/干净的方法,但你可以做类似 df %&gt;% mutate(ord = row_number()) %&gt;% group_by(name) %&gt;% fill(var2) %&gt;% arrange(ord) %&gt;% select(-ord) 或使用 arrange 如果有可能是连续的日期这样的另一个字段。
    【解决方案2】:

    我们可以在按'name'分组后使用replace

    library(dplyr)
    df %>% 
      group_by(name)  %>% 
      mutate(var2 = replace(var2, is.na(var2), var2[!is.na(var2)]))
    

    【讨论】:

      【解决方案3】:

      在基础 R

      df2 <- merge(df1[1],subset(df1,!is.na(var2),all.x=TRUE))
      
      #    name var2
      # 1  abye  104
      # 2  abye  104
      # 3  abye  104
      # 4  abye  104
      # 5  glqy  102
      # 6  glqy  102
      # 7  glqy  102
      # 8  glqy  102
      # 9  gryh  102
      # 10 gryh  102
      # 11 gryh  102
      # 12 gryh  102
      # 13 yygy  101
      # 14 yygy  101
      # 15 yygy  101
      # 16 yygy  101
      

      或保持秩序:

      df2 <- merge(df1[1],subset(df1,!is.na(var2),all.x=TRUE)
                   )[rank(df1$name,ties.method="first"),]
      rownames(df2) <- NULL
      
      #    name var2
      # 1  yygy  101
      # 2  gryh  102
      # 3  glqy  102
      # 4  abye  104
      # 5  yygy  101
      # 6  gryh  102
      # 7  glqy  102
      # 8  abye  104
      # 9  yygy  101
      # 10 gryh  102
      # 11 glqy  102
      # 12 abye  104
      # 13 yygy  101
      # 14 gryh  102
      # 15 glqy  102
      # 16 abye  104
      

      数据

      name<- rep(c("yygy","gryh","glqy","abye"),4)
      var2<- c(101,102,102,104,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA)
      df1 <- data.frame(name,var2)
      

      【讨论】:

      • 我认为,如果我的数据框中的数据列不超过 2 个,这将是可以的,但是有并且它似乎因此而混乱(对不起,我应该说)。感谢您的意见。 Sbha 的回答似乎完成了这项工作。
      • 如果您使用df1[-2] 而不是df1[1]subset(df1[c("name","var2")],!is.na(var2)) 它应该可以工作(使用列的正确索引而不是2)
      • sbha 的解决方案是最好的方法,如果您使用dplyr,我会使用它(我已经开始输入它:)),我只是提供基本的替代方案。但它不会保留顺序。
      最近更新 更多