【问题标题】:Replace values in one column based on another dataframe in R根据 R 中的另一个数据框替换一列中的值
【发布时间】:2020-09-01 14:52:54
【问题描述】:

我有一个超过 20k obs 的数据框。其中一列是“城市名称”(df$city)。有超过 600 个独特的城市名称。其中一些拼写错误。

我的数据框示例:

> df$city
[1] "BOSTN" "LOS ANGELOS" "NYC" "CHICAGOO" 
[2] "SEATTLE" "BOSTON" "NEW YORK CITY"

我创建了一个 csv 文件,其中列出了所有拼写错误的城市名称以及正确的名称。

> head(city)
           city    city_incorrect
1 BOSTON                    BOSTN
2 LOS ANGELES         LOS ANGELOS
3 NEW YORK CITY               NYC
4 CHICAGO                CHICAGOO

理想情况下,我会编写代码,根据“city.csv”文件替换 df$city 中的值。

注意:我最初发布了这个问题,有人建议我使用合并,我认为这不是解决我的问题的最有效方法,因为我还必须在我的 " city.csv”文件。或者我认为我需要一个额外的步骤来组合合并数据框中的两列。所以我认为根据“city.csv”替换df$city中的值可能更容易。

编辑: 这是对我的数据框的更详细了解

> df[1:5]
id   owner   city            state
1    AAAAA   BOSTN              MA
2    BBBBB   LOS ANGELOS        CA
3    CCCCC   NYC                NY
4    DDDDD   CHICAGOO           IL
5    EEEEE   BOSTON             MA
6    FFFFF   SEATTLE            WA
7    GGGGG   NEW YORK CITY      NY
8    HHHHH   LOS ANGELES        CA

如果我使用合并或 cbind,它不会像这样在我的数据框末尾创建另一列:

> merge()
id   owner   city            state     city_correct
1    AAAAA   BOSTN              MA           BOSTON
2    BBBBB   LOS ANGELOS        CA      LOS ANGELES
3    CCCCC   NYC                NY    NEW YORK CITY
4    DDDDD   CHICAGOO           IL          CHICAGO
5    EEEEE   BOSTON             MA
6    FFFFF   SEATTLE            WA
7    GGGGG   NEW YORK CITY      NY
8    HHHHH   LOS ANGELES        CA

因此,拼写错误的城市将被纠正,但拼写正确的城市将被排除在外。我最终想要的是一列包含所有更正的城市名称。

【问题讨论】:

  • 城市是否逐行匹配,或者您想要部分字符串匹配?如果是逐行,“简单”的 cbind 可以吗?
  • @NelsonGon 嗨!我认为合并选项不是我想要的?我编辑了我的原始帖子,希望有助于澄清我的问题。
  • 不,您不必在 csv 中包含正确拼写的城市即可使用 merge。执行left_join,right_join(取决于您如何安排数据集),然后执行coalesce。只是不要进行内部连接。召回加入类似于合并

标签: r replace multiple-columns


【解决方案1】:

base::merge() 的一种方法是在查找表中包含具有正确城市值的行,并将该表与原始数据合并。我们将调用“正确”的城市名称correctedCity,并合并如下:

cityText <- "id,owner,city,state
1,AAAAA,BOSTN,MA
2,BBBBB,LOS ANGELOS,CA
3,CCCCC,NYC,NY
4,DDDDD,CHICAGOO,IL
5,EEEEE,BOSTON,MA
6,FFFFF,SEATTLE,WA
7,GGGGG,NEW YORK CITY,NY
8,HHHHH,LOS ANGELES,CA"

cities <- read.csv(text = cityText, header = TRUE, stringsAsFactors = FALSE)

# first, find all the distinct versions of city
library(sqldf)
distinctCities <- sqldf("select city, count(*) as count from cities group by city")

# create lookup table, and include rows for items that are already correct 
tableText <- "city,correctedCity
BOSTN,BOSTON
BOSTON,BOSTON
CHICAGOO,CHIGAGO
LOS ANGELES,LOS ANGELES
LOS ANGELOS,LOS ANGELES
NEW YORK CITY,NEW YORK CITY
NYC,NEW YORK CITY
SEATTLE,SEATTLE"

cityTable <- read.csv(text = tableText,header = TRUE,stringsAsFactors = FALSE)
corrected <- merge(cities,cityTable,by = "city")
corrected

...和输出:

> corrected
           city id owner state correctedCity
1         BOSTN  1 AAAAA    MA        BOSTON
2        BOSTON  5 EEEEE    MA        BOSTON
3      CHICAGOO  4 DDDDD    IL       CHIGAGO
4   LOS ANGELES  8 HHHHH    CA   LOS ANGELES
5   LOS ANGELOS  2 BBBBB    CA   LOS ANGELES
6 NEW YORK CITY  7 GGGGG    NY NEW YORK CITY
7           NYC  3 CCCCC    NY NEW YORK CITY
8       SEATTLE  6 FFFFF    WA       SEATTLE
>

此时可以删除原始值并保留更正的版本。

# rename & keep corrected version
library(dplyr)
corrected %>% select(-city) %>% rename(city = correctedCity) 

如 cmets 中所述,OP 的替代方法是创建一个查找表,其中仅包含拼写错误的城市名称的行。在这种情况下,我们将使用merge() 中的参数all.x = TRUE 来保留主数据框中的所有行,并将correctedCity 的非缺失值分配给city

tableText <- "city,correctedCity
BOSTN,BOSTON
CHICAGOO,CHIGAGO
LOS ANGELOS,LOS ANGELES
NYC,NEW YORK CITY"

cityTable <- read.csv(text = tableText,header = TRUE,stringsAsFactors = FALSE)
corrected <- merge(cities,cityTable,by = "city",all.x = TRUE)
corrected$city[!is.na(corrected$correctedCity)] <- corrected$correctedCity[!is.na(corrected$correctedCity)]
corrected

...和输出:

> corrected
           city id owner state correctedCity
1        BOSTON  1 AAAAA    MA        BOSTON
2        BOSTON  5 EEEEE    MA          <NA>
3       CHIGAGO  4 DDDDD    IL       CHIGAGO
4   LOS ANGELES  8 HHHHH    CA          <NA>
5   LOS ANGELES  2 BBBBB    CA   LOS ANGELES
6 NEW YORK CITY  7 GGGGG    NY          <NA>
7 NEW YORK CITY  3 CCCCC    NY NEW YORK CITY
8       SEATTLE  6 FFFFF    WA          <NA>
> 

此时,correctedCity 可以从数据框中删除。

【讨论】:

    【解决方案2】:

    在我看来,您要做的是将一个数据框中的不正确城市名称匹配并替换为另一个数据框中的正确城市名称。如果这是正确的,那么这个dplyr 解决方案应该可以工作。

    数据

    具有正确和错误城市名称对的数据框:

    city <- data.frame(
      city_correct = c("BOSTON", "LOS ANGELES", "NEW YORK CITY", "CHICAGO"),
      city_incorrect = c("BOSTN", "LOS ANGELOS", "NYC", "CHICAGOO"), stringsAsFactors = F)
    

    混合了正确和错误城市名称的数据框:

    set.seed(123)
    df <- data.frame(town = sample(c("BOSTON", "LOS ANGELES", "NEW YORK CITY", "CHICAGO","BOSTN", 
                                     "LOS ANGELOS", "NYC", "CHICAGOO"), 20, replace = T), stringsAsFactors = F)
    

    解决方案

    library(dplyr)
    df <- left_join(df, city, by = c("town" = "city_incorrect"))
    df$town_correct<-ifelse(is.na(df$city_correct), df$town, df$city_correct)
    df$city_correct <- NULL
    

    编辑:

    另一个,base R,解决方案是这样的:

    df$town_correct <- ifelse(df$town %in% city$city_incorrect, 
                              city$city_correct[match(df$town, city$city_incorrect)], 
                              df$town[match(df$town, city$city_correct)])
    

    结果

    df
                town  town_correct
    1  NEW YORK CITY NEW YORK CITY
    2            NYC NEW YORK CITY
    3        CHICAGO       CHICAGO
    4       CHICAGOO       CHICAGO
    5       CHICAGOO       CHICAGO
    6         BOSTON        BOSTON
    7          BOSTN        BOSTON
    8       CHICAGOO       CHICAGO
    9          BOSTN        BOSTON
    10       CHICAGO       CHICAGO
    11      CHICAGOO       CHICAGO
    12       CHICAGO       CHICAGO
    13   LOS ANGELOS   LOS ANGELES
    14         BOSTN        BOSTON
    15        BOSTON        BOSTON
    16      CHICAGOO       CHICAGO
    17   LOS ANGELES   LOS ANGELES
    18        BOSTON        BOSTON
    19 NEW YORK CITY NEW YORK CITY
    20      CHICAGOO       CHICAGO
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-23
      • 2021-09-08
      相关资源
      最近更新 更多