【问题标题】:How to convert string in value to attributes and values?如何将值中的字符串转换为属性和值?
【发布时间】:2021-06-30 13:31:57
【问题描述】:

我有 3mio 观察,属性为“other_tags”。 “other_tags”的值必须转换为新的属性和值。

输入()

structure(list(osm_id = c(105093, 107975, 373652), other_tags = structure(c(2L, 
3L, 1L), .Label = c("\"addr:city\"=>\"Neuenegg\",\"addr:street\"=>\"Stuberweg\",\"building\"=>\"school\",\"building:levels\"=>\"2\"", 
"\"building\"=>\"commercial\",\"name\"=>\"Pollahof\",\"type\"=>\"multipolygon\"", 
"\"building\"=>\"yes\",\"amenity\"=>\"sport\",\"type\"=>\"multipolygon\""
), class = "factor")), class = "data.frame", row.names = c(NA, 
-3L))

这是数据的子样本:

osm_id  other_tags
105093  "building"=>"commercial","name"=>"Pollahof","type"=>"multipolygon"
107975  "building"=>"yes","amenity"=>"sport","type"=>"multipolygon"
373652  "addr:city"=>"Neuenegg","addr:street"=>"Stuberweg","building"=>"school","building:levels"=>"2"

这是所需的数据格式:创建新属性(仅用于建筑和便利设施)并添加值。

osm_id  building    amenity
105093  commercial
107975  yes         sport
373652  school

感谢您的帮助!

【问题讨论】:

  • 您需要为所寻求的提取定义规则:通过什么规则可以例如在字符串中检测到值sport?还可以使用dput() 发布最小可重复数据样本。
  • 天哪,便利设施包含在第二行(已编辑)中。所以没有规则。只要存在便利设施,它就应该使列“便利设施”和价值。我还用 dput 添加了数据样本

标签: r dataframe gis openstreetmap


【解决方案1】:

没那么难。

  • other_tags 是因子列,所以我们必须在上面使用as.charachter
  • 提取结果会生成一个中间列表,例如 s,其中所有变量都是分开的;使用strsplit 将这些从split = ',' 拆分后
  • 将这些属性存储在 seaparte rwo 中,为新数据框中的每个属性,比如 df2
  • 使用tidyr 中的separate() 将属性名称和值分成两个单独的列。分隔符sep 这次用作=>
  • 使用str_remove_all 删除多余的引号
  • 可选filter数据集
  • pivot_wider 转换成所需的格式。
library(tidyverse)

s <- strsplit(as.character(df$other_tags), split = ",")

df2 <- data.frame(osm_id = rep(df$osm_id, sapply(s, length)), other_tags = unlist(s))

df2 %>% separate(other_tags, into = c("Col1", "Col2"), sep = "=>") %>%
  mutate(across(starts_with("Col"), ~str_remove_all(., '"'))) %>%
  filter(Col1 %in% c("amenity", "building")) %>%
  pivot_wider(id_cols = osm_id, names_from = Col1, values_from = Col2)

# A tibble: 3 x 3
  osm_id building   amenity
   <dbl> <chr>      <chr>  
1 105093 commercial NA     
2 107975 yes        sport  
3 373652 school     NA    

如果不使用过滤器

df2 %>% separate(other_tags, into = c("Col1", "Col2"), sep = "=>") %>%
  mutate(across(starts_with("Col"), ~str_remove_all(., '"'))) %>%
  pivot_wider(id_cols = osm_id, names_from = Col1, values_from = Col2)

# A tibble: 3 x 8
  osm_id building   name     type         amenity `addr:city` `addr:street` `building:levels`
   <dbl> <chr>      <chr>    <chr>        <chr>   <chr>       <chr>         <chr>            
1 105093 commercial Pollahof multipolygon NA      NA          NA            NA               
2 107975 yes        NA       multipolygon sport   NA          NA            NA               
3 373652 school     NA       NA           NA      Neuenegg    Stuberweg     2 

单管道语法

df %>% mutate(other_tags = as.character(other_tags),
              other_tags = str_split(other_tags, ",")) %>%
  unnest(other_tags) %>%
  mutate(other_tags = str_remove_all(other_tags, '"')) %>%
  separate(other_tags, into = c("Col1", "Col2"), sep = "=>") %>%
  filter(Col1 %in% c("amenity", "building")) %>%
  pivot_wider(id_cols = osm_id, names_from = Col1, values_from = Col2)

# A tibble: 3 x 3
  osm_id building   amenity
   <dbl> <chr>      <chr>  
1 105093 commercial NA     
2 107975 yes        sport  
3 373652 school     NA   

【讨论】:

  • 谢谢这工作!单管道语法是顶部。
【解决方案2】:

我们可以使用(g)substr_extract 以及环视(只需两行代码):

library(stringr)
df$building <- str_extract(gsub('"','', df$other_tags),'(?<=building=>)\\w+(?=,)')
df$amenity <- str_extract(gsub('"','', df$other_tags),'(?<=amenity=>)\\w+(?=,)')

如果出于某种原因您想删除列other_tags

df$other_tags <- NULL

结果:

df
  osm_id   building amenity
1 105093 commercial    <NA>
2 107975        yes   sport
3 373652     school    <NA>

【讨论】:

  • 感谢您的感谢。坦率地说,我不明白为什么一个相当复杂的解决方案比透明的经济解决方案更受欢迎......
  • 也许那是因为您的答案并没有真正产生所需的输出,并且仅适用于迷你示例,不适用于一般情况...
  • 你怎么知道它对一般情况不起作用?而且它没有产生所需的输出是可笑的......如果 OP 出于某种原因不能以任何方式保留原始列,那么他们只需将其设置为 NULL!
猜你喜欢
  • 2018-11-18
  • 1970-01-01
  • 2019-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
相关资源
最近更新 更多