【问题标题】:Replacing NAs in a dataframe based on a partial string match (in another dataframe) in R根据R中的部分字符串匹配(在另一个数据帧中)替换数据帧中的NA
【发布时间】:2021-08-11 05:23:41
【问题描述】:

目标:根据另一个数据帧中的“键”更改一个数据帧中的一列 NA(类似于 VLookUp,仅在 R 中除外)

在这里给定 df1(为了简单起见,我只有 6 行。我拥有的关键是 50 行,用于 50 个状态):

Index State_Name Abbreviation
1 California CA
2 Maryland MD
3 New York NY
4 Texas TX
5 Virginia VA
6 Washington WA

这里给出了 df2(这只是一个例子。我正在使用的真实数据框有更多行):

Index State Article
1 NA Texas governor, Abbott, signs new abortion bill
2 NA Effort to recall California governor Newsome loses steam
3 NA New York governor, Cuomo, accused of manipulating Covid-19 nursing home data
4 NA Hogan (Maryland, R) announces plans to lift statewide Covid restrictions
5 NA DC statehood unlikely as Manchin opposes
6 NA Amazon HQ2 causing housing prices to soar in northern Virginia

任务:创建一个循环并读取每个 df2$Article 行中的状态的 R 函数;然后将其与 df1$State_Name 交叉引用,以根据 df2$Article 中的状态用相应的 df1$Abbreviation 键替换 df2$State 中的 NA。我知道这很拗口。我不知道如何开始和完成这个难题。硬编码不是一个选项,因为我有数千行这样的真实数据表,并且会随着我们向文本抓取添加更多文章而更新。

输出应如下所示:

Index State Article
1 TX Texas governor, Abbott, signs new abortion bill
2 CA Effort to recall California governor Newsome loses steam
3 NY New York governor, Cuomo, accused of manipulating Covid-19 nursing home data
4 MD Hogan (Maryland, R) announces plans to lift statewide Covid restrictions
5 NA DC statehood unlikely as Manchin opposes
6 VA Amazon HQ2 causing housing prices to soar in northern Virginia

注意:带有 DC 的第五个条目应为 NA。

非常感谢任何指向指南的链接和/或有关如何编码的任何建议。谢谢!

【问题讨论】:

    标签: r dataframe dplyr na string-matching


    【解决方案1】:

    您可以从State_Name 创建一个正则表达式模式,并使用str_extractArticle 中提取它。使用matchdf1获取对应的Abbreviation名称。

    library(stringr)
    
    df2$State <- df1$Abbreviation[match(str_extract(df2$Article, 
                   str_c(df1$State_Name, collapse = '|')), df1$State_Name)]
    df2$State
    #[1] "TX" "CA" "NY" "MD" NA   "VA"
    

    您还可以使用内置的state.namestate.abb 代替df1 来获取州名和缩写。


    这是在 for 循环中执行此操作的方法 -

    for(i in seq(nrow(df1))) {
      inds <- grep(df1$State_Name[i], df2$Article)
      if(length(inds)) df2$State[inds] <- df1$Abbreviation[i]
    }
    df2
    
    #  Index State                                                                      Article
    #1     1    TX                              Texas governor, Abbott, signs new abortion bill
    #2     2    CA                     Effort to recall California governor Newsome loses steam
    #3     3    NY New York governor, Cuomo, accused of manipulating Covid-19 nursing home data
    #4     4    MD     Hogan (Maryland, R) announces plans to lift statewide Covid restrictions
    #5     5  <NA>                                     DC statehood unlikely as Manchin opposes
    #6     6    VA               Amazon HQ2 causing housing prices to soar in northern Virginia
    

    【讨论】:

    • 所以我在玩这个代码 sn-p,它适用于更简单的数据框。但是,对于我正在处理的数据框,我不断收到 Null 错误。有没有一种方法可以让我通过 df1 (df1$State_name) 中的每个状态创建一个循环(很可能是 for),然后根据文章名称在 df2$State 中写入正确的缩写?本质上,结果相同,但有一个循环。不过,非常感谢您带路!
    • @llew88 查看更新后的答案以使用for 循环执行此操作。
    【解决方案2】:

    不像上面那样简洁,而是一个Base R方法:

    # Unlist handling 0 length vectors: list_2_vec => function()
    list_2_vec <- function(lst){
      # Coerce 0 length vectors to na values of the appropriate type: 
      # .zero_to_nas => function()
      .zero_to_nas <- function(x){
        if(identical(x, character(0))){
          NA_character_ 
        }else if(identical(x, integer(0))){
          NA_integer_
        }else if(identical(x, numeric(0))){
          NA_real_
        }else if(identical(x, complex(0))){
          NA_complex_
        }else if(identical(x, logical(0))){
          NA
        }else{
          x
        }
      }
      # Unlist cleaned list: res => vector
      res <- unlist(lapply(lst, .zero_to_nas))
      # Explictly define return object: vector => GlobalEnv()
      return(res)
    }
    
    # Classify each article as belonging to the appropriate state: 
    # clean_df => data.frame
    clean_df <- transform(
      df2,
      State = df1$Abbreviation[
        match(
          list_2_vec(
            regmatches(
              Article, 
              gregexpr(
                paste0(df1$State_Name, collapse = "|"), Article
              )
            )
          ),
          df1$State_Name
        )
      ]
    )
    
    # Data: 
    df1 <- structure(list(Index = 1:6, State_Name = c("California", "Maryland", 
    "New York", "Texas", "Virginia", "Washington"), Abbreviation = c("CA", 
    "MD", "NY", "TX", "VA", "WA")), class = "data.frame", row.names = c(NA, -6L))
    
    df2 <- structure(list(Index = 1:6, State = c(NA, NA, NA, NA, NA, NA), 
    Article = c("Texas governor, Abbott, signs new abortion bill", 
    "Effort to recall California governor Newsome loses steam", 
    "New York governor, Cuomo, accused of manipulating Covid-19 nursing home data", 
    "Hogan (Maryland, R) announces plans to lift statewide Covid restrictions", 
    "DC statehood unlikely as Manchin opposes", "Amazon HQ2 causing housing prices to soar in northern Virginia"
    )), class = "data.frame", row.names = c(NA, -6L))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-10
      • 2014-09-20
      • 1970-01-01
      • 1970-01-01
      • 2021-11-21
      • 2020-03-29
      • 2018-12-08
      • 1970-01-01
      相关资源
      最近更新 更多