拆分字符串并根据模式提取以形成数据帧

时间:2017-04-19 02:42:56

标签: r regex stringr strsplit

我正在尝试将以下字符串切割为R

中的3个分隔列(Country,City,Count)
Country    City     Count    
Japan      Tokyo    361

数据:

"country=Japan&city=Tokyo","361"
"country=Spain&city=Barcelona","359"
"country=United Kingdom&city=London","333"
"country=Japan&city=Fukuoka","259"
"country=United States of America&city=New York City","223"

我试过这个:

library(data.table)
library(stringr)

df <- read.table(file.choose(), header = FALSE, sep = ",", colClasses = c('character', 'character'), na.strings = 'null')

df.1 <- data.table(str = as.character(df$V1))

df.2 <- df.1[grepl("country=.+&city=\\w+", str),
             country := str_extract(str,"(?<=country=)(.+)"),
             city := str_extract(str, "(?<=city=)(.+)")]

但是从这一点来看,虽然我希望查看城市格式,但列国家将返回如下:

Japan&city=Tokyo

我想取消&amp; city = Tokyo位以制作漂亮的格式。

然后,我将df和df.2合并在一起,所以我将数字值对齐。但是,我认为必须有一个更聪明的方法来做到这一点。

请与我分享您的知识。感谢您的协助。

2 个答案:

答案 0 :(得分:2)

我们可以使用base R strsplit将“{1}}和=的”V1“列拆分为&,循环遍历list },提取替代元素(list),同时使用其余元素命名,x[c(FALSE, TRUE)] rbind元素,然后list和第二列原始数据集

cbind

我们也可以使用res <- do.call(rbind, lapply(strsplit(as.character(df$V1), "[=&]"), function(x) setNames(x[c(FALSE, TRUE)], x[c(TRUE, FALSE)]))) res1 <- cbind(res, setNames(df[-1], 'Count')) res1 # country city Count #1 Japan Tokyo 361 #2 Spain Barcelona 359 #3 United Kingdom London 333 #4 Japan Fukuoka 259 #5 United States of America New York City 223 执行此操作。从tidyverse创建行索引列(rownames_to_column),然后将分隔符'&amp;'拆分为'V1' (tibble)重塑为'long'格式,通过将'sep'指定为separate_rows将'V1'拆分为新列('new1'和'new2'),将数据集重新整形为'wide'(=)并重新排序列(spread

select

数据

library(tidyverse)
rownames_to_column(df, 'rn') %>%
      separate_rows(V1, sep='[&]') %>% 
      separate(V1, into= c("new1", "new2"), sep="=")  %>% 
      spread(new1, new2) %>% 
      select(country, city, Count=V2) 
#                   country          city Count
#1                    Japan         Tokyo   361
#2                    Spain     Barcelona   359
#3           United Kingdom        London   333
#4                    Japan       Fukuoka   259
#5 United States of America New York City   223

答案 1 :(得分:2)

您拥有的是有效的URL编码查询,因此您可以使用httr::parse_url对其进行解码。两个并发症:

  1. parse_url在查询前面查找?以识别它,因此您必须paste0开启,
  2. parse_url未进行矢量化,因此必须通过lapplypurrr::map将其应用于每个查询。
  3. 但大多数情况下,它的效果非常好:

    library(tidyverse)
    
    df <- read_csv('"country=Japan&city=Tokyo","361"
    "country=Spain&city=Barcelona","359"
    "country=United Kingdom&city=London","333"
    "country=Japan&city=Fukuoka","259"
    "country=United States of America&city=New York City","223"', 
                   col_names = c('query', 'count'))
    
    df %>% transmute(count, 
                     query = map(paste0('?', query), 
                                 ~as_data_frame(httr::parse_url(.x)$query))) %>% 
        unnest()
    
    #> # A tibble: 5 × 3
    #>   count                  country          city
    #>   <int>                    <chr>         <chr>
    #> 1   361                    Japan         Tokyo
    #> 2   359                    Spain     Barcelona
    #> 3   333           United Kingdom        London
    #> 4   259                    Japan       Fukuoka
    #> 5   223 United States of America New York City
    

    甚至只是

    df %>% do(data.frame(count = .$count, 
                         query = map_df(paste0('?', .$query), 
                                        ~httr::parse_url(.x)$query)))
    

    或使用curlconverter::parse_queryshiny::parseQueryString,不需要额外的?

    df %>% bind_cols(map_df(.$query, curlconverter::parse_query)) %>% select(-query)
    

    所有回报都是一样的。