我正在尝试将以下字符串切割为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合并在一起,所以我将数字值对齐。但是,我认为必须有一个更聪明的方法来做到这一点。
请与我分享您的知识。感谢您的协助。
答案 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
对其进行解码。两个并发症:
parse_url
在查询前面查找?
以识别它,因此您必须paste0
开启,parse_url
未进行矢量化,因此必须通过lapply
或purrr::map
将其应用于每个查询。但大多数情况下,它的效果非常好:
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_query
或shiny::parseQueryString
,不需要额外的?
:
df %>% bind_cols(map_df(.$query, curlconverter::parse_query)) %>% select(-query)
所有回报都是一样的。