代码之家  ›  专栏  ›  技术社区  ›  Girijesh Singh

R列映射

  •  1
  • Girijesh Singh  · 技术社区  · 8 年前

    如何将一个CSV文件的列映射到R中另一个CSV文件的列。如果两者的数据类型相同。 例如,数据框A的第一列包含一些包含国家名称的文本。而第二个数据框B的列包含所有国家的标准列表。现在,我必须用标准国家列映射第一个数据框的所有行。

    例如,数据框A的列(位置)由10000行数据组成,如下所示

    Sydney, Australia
    Aarhus C, Central Region, Denmark
    Auckland, New Zealand
    Mumbai Area, India
    Singapore
    df1 <- data.frame(col1 = 1:5, col2=c("Sydney, Australia", "Aarhus C, Central Region, Denmark", "Auckland, New Zealand", "Mumbai Area, India", "Singapore"))
    

    现在我有了数据框B的另一列(国家),如

    India
    USA
    New Zealand
    UK
    Singapore
    Denmark
    China
    df2 <- data.frame(col1=1:7, col2=c("India", "USA", "New Zealand", "UK", "Singapore", "Denmark", "China"))
    

    如果location列与Country列匹配,那么我想用Country名称替换该位置,否则它将保持原样。样本输出为

    Sydney, Australia
    Denmark
    New Zealand
    India
    Singapore
    
    3 回复  |  直到 8 年前
        1
  •  1
  •   YOLO    8 年前

    起初,这看起来像一个微不足道的问题,但事实并非如此。这种方法的工作原理如下:

    1、我们使用 unlist , strsplit .
    2、然后我们检查向量中的任何字符串在country列中是否可用。如果可用,我们将国家名称存储在 res 如果不是我们存储 notfound .
    2.最后,我们检查res是否包含国家名称。

    df1 <- data.frame(location = c('Sydney, Australia',
                  'Aarhus C, Central Region, Denmark',
                  'Auckland, New Zealand',
                  'Mumbai Area, India',
              'Singapore'),stringsAsFactors = F)
    
    
    df2 <- data.frame(country = c('India',
                                   'USA',
                                   'New Zealand',
                                   'UK',
                                   'Singapore',
                                   'Denmark',
                                   'China'),stringsAsFactors = F)
    
    
    get_values <- function(i)
    {
        val <- unlist(strsplit(i, split = ','))
        val <- sapply(val, str_trim)
    
        res <- c()
        for(j in val)
        {
            if(j %in% df2$country) res <- append(res, j)
            else res <- append(res, 'notfound')
        }
    
        if(all(res == 'notfound')) return (i)
        else return (res[res!='notfound'])
    
    }
    
    df1$location2 <- sapply(df1$location, get_values)
    
                               location         location2
    1                 Sydney, Australia Sydney, Australia
    2 Aarhus C, Central Region, Denmark           Denmark
    3             Auckland, New Zealand       New Zealand
    4                Mumbai Area, India             India
    5                         Singapore         Singapore
    
        2
  •  1
  •   www    8 年前

    解决方案使用 . 首先,请转换您的 col2 按设置设置字符 stringsAsFactors = FALSE 因为这更容易处理。

    我们可以使用 str_extract 提取匹配的国家名称,然后创建新的 col2 具有 mutate ifelse .

    df3 <- df1 %>%
      mutate(Country = str_extract(col2, paste0(df2$col2, collapse = "|")),
             col2 = ifelse(is.na(Country), col2, Country)) %>%
      select(-Country)
    df3
    #   col1              col2
    # 1    1 Sydney, Australia
    # 2    2           Denmark
    # 3    3       New Zealand
    # 4    4             India
    # 5    5         Singapore
    

    我们也可以从 df1 使用 separate_rows 分隔国家名称。之后,使用 semi_join 检查国家名称是否在 df2 . 最后,我们可以将数据帧与原始数据帧相结合 df1型 按行,然后为中的每个id筛选第一个 col1 . df3 是最终输出。

    library(tidyverse)
    
    df3 <- df1 %>%
      separate_rows(col2, sep = ", ") %>%
      semi_join(df2, by = "col2") %>%
      bind_rows(df1) %>%
      group_by(col1) %>%
      slice(1) %>%
      ungroup() %>%
      arrange(col1)
    df3
    # # A tibble: 5 x 2
    #    col1 col2             
    #   <int> <chr>            
    # 1     1 Sydney, Australia
    # 2     2 Denmark          
    # 3     3 New Zealand      
    # 4     4 India            
    # 5     5 Singapore
    

    数据

    df1 <- data.frame(col1 = 1:5, 
                      col2=c("Sydney, Australia", "Aarhus C, Central Region, Denmark", "Auckland, New Zealand", "Mumbai Area, India", "Singapore"),
                      stringsAsFactors = FALSE)
    
    df2 <- data.frame(col1=1:7, 
                      col2=c("India", "USA", "New Zealand", "UK", "Singapore", "Denmark", "China"),
                      stringsAsFactors = FALSE)
    
        3
  •  1
  •   Onyambu    8 年前

    如果你在寻找国家,而他们在寻找城市,那么你可以这样做。

      transform(df1,col3= sub(paste0(".*,\\s*(",paste0(df2$col2,collapse="|"),")"),"\\1",col2))
      col1                              col2              col3
    1    1                 Sydney, Australia Sydney, Australia
    2    2 Aarhus C, Central Region, Denmark           Denmark
    3    3             Auckland, New Zealand       New Zealand
    4    4                Mumbai Area, India             India
    5    5                         Singapore         Singapore
    

    细分:

    > A=sub(".*,\\s(.*)","\\1",df1$col2)
    > B=sapply(A,grep,df2$col2,value=T)
    > transform(df1,col3=replace(A,!lengths(B),col2[!lengths(B)]))
      col1                              col2              col3
    1    1                 Sydney, Australia Sydney, Australia
    2    2 Aarhus C, Central Region, Denmark           Denmark
    3    3             Auckland, New Zealand       New Zealand
    4    4                Mumbai Area, India             India
    5    5                         Singapore         Singapore