Как создать список-столбцы из списка в R? - PullRequest
0 голосов
/ 13 июня 2018
# Sample data
df <- tibble(id=1:2, xml_str=c("<?xml version='1.0'?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg version='1.1' xmlns='http://www.w3.org/2000/svg'>'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M171, 160 L171, 160, 168, 159, 164, 159, 163, 159, 162, 159, 161, 159, 161, 158, 162, 158, 162, 157, 163, 156, 165, 156'/>'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M172, 226 L172, 226, 171, 213, 170, 212, 171, 212, 172, 212, 173, 212, 173, 211, 172, 211, 171, 211, 171, 212, 171, 215'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M153, 94 L153, 94, 150, 90, 150, 89, 150, 88, 150, 87, 150, 86, 150, 85, 150, 84, 150, 82, 150, 81, 150, 80, 150, 79'/>'/>'/>'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M346, 84 L346, 84, 346, 79, 347, 78, 347, 77, 348, 77, 348, 76, 348, 75, 348, 76, 348, 77, 349, 77, 348, 78'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M314, 67 L314, 67, 311, 76, 309, 76, 308, 77, 307, 77, 307, 76, 306, 76, 305, 76, 305, 77, 306, 77, 307, 77, 306, 77, 305, 79, 304, 80'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M313, 57 L313, 57, 321, 56, 321, 57, 321, 58'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M332, 58 L332, 58, 332, 57, 331, 57, 333, 57, 334, 57, 335, 57, 336, 58, 337, 58, 338, 58, 339, 58, 340, 58, 341, 58, 341, 59, 340, 60, 339, 60, 338, 60, 337, 60, 336, 60, 335, 60, 334, 60, 333, 60, 332, 60, 331, 60, 331, 59, 333, 58, 334, 58'/></svg>", "<?xml version='1.0'?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg version='1.1' xmlns='http://www.w3.org/2000/svg'>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M315, 80 L315, 80, 321, 79, 320, 79, 318, 79, 317, 79'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M334, 83 L334, 83, 334, 82'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M315, 80 L315, 80, 315, 82, 315, 83, 315, 84, 315, 85'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M315, 72 L315, 72'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M315, 69 L315, 69, 315, 70'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M332, 66 L332, 66, 332, 67'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M315, 56 L315, 56'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M315, 66 L315, 66, 315, 67'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M315, 72 L315, 72'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M332, 72 L332, 72, 333, 75'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M315, 72 L315, 72'/>\n<path fill='none' stroke='#ff0000' stroke-width='5' d='M334, 73 L334, 73, 333, 73'/></svg>"))

df <- df %>% 
  rowwise() %>% 
  mutate(nodes = (xml_str %>% read_xml() %>% xml_find_all(., "//@d") %>% as_list()))

С указанным выше фреймом данных я хочу извлечь все d-узлы элемента пути из строки xml и сохранить их как список в одном и том же фрейме данных, но я получаю, что столбец nodes должен иметь длину 1(размер группы), а не 7

Трубопровод, используемый в операторе mutate, возвращает один список .

Я могу опустить 'rowwise ()',но это просто ожидает длину 2 вместо 1.

Чего мне здесь не хватает?

Ответы [ 2 ]

0 голосов
/ 13 июня 2018

Делает ли это то, что вы хотите?Обычно для этого я оборачиваю правую сторону моего mutate(name = right_side) в list().

df <- df %>% 
    mutate(nodes = list(xml_str %>% read_xml() %>% xml_find_all(., "//@d")))

class(df$nodes)
"list"
class(df$nodes[[1]])
"xml_nodeset"

Не уверен, хотите ли вы, чтобы объекты xml_nodeset или, возможно, решение CPak с реальными строками было бы вам лучше.

0 голосов
/ 13 июня 2018

Это не совсем то, что вы делаете, но вы можете использовать str_extract_all и регулярное выражение, чтобы извлечь соответствующую строку в виде списка разделенных запятыми строк

ans <- 
  df %>%
    dplyr::mutate(dnodes = stringr::str_extract_all(xml_str, "(?<=[d]=')[^']+(?='\\/)"))

ans$dnodes
# [[1]]
# [1] "M171, 160 L171, 160, 168, 159, 164, 159, 163, 159, 162, 159, 161, 159, 161, 158, 162, 158, 162, 157, 163, 156, 165, 156"                                                                                                                           
# [2] "M172, 226 L172, 226, 171, 213, 170, 212, 171, 212, 172, 212, 173, 212, 173, 211, 172, 211, 171, 211, 171, 212, 171, 215"                                                                                                                           
# [3] "M153, 94 L153, 94, 150, 90, 150, 89, 150, 88, 150, 87, 150, 86, 150, 85, 150, 84, 150, 82, 150, 81, 150, 80, 150, 79"                                                                                                                              
# [4] "M346, 84 L346, 84, 346, 79, 347, 78, 347, 77, 348, 77, 348, 76, 348, 75, 348, 76, 348, 77, 349, 77, 348, 78"                                                                                                                                       
# [5] "M314, 67 L314, 67, 311, 76, 309, 76, 308, 77, 307, 77, 307, 76, 306, 76, 305, 76, 305, 77, 306, 77, 307, 77, 306, 77, 305, 79, 304, 80"                                                                                                            
# [6] "M313, 57 L313, 57, 321, 56, 321, 57, 321, 58"                                                                                                                                                                                                      
# [7] "M332, 58 L332, 58, 332, 57, 331, 57, 333, 57, 334, 57, 335, 57, 336, 58, 337, 58, 338, 58, 339, 58, 340, 58, 341, 58, 341, 59, 340, 60, 339, 60, 338, 60, 337, 60, 336, 60, 335, 60, 334, 60, 333, 60, 332, 60, 331, 60, 331, 59, 333, 58, 334, 58"

# [[2]]
 # [1] "M315, 80 L315, 80, 321, 79, 320, 79, 318, 79, 317, 79" "M334, 83 L334, 83, 334, 82"                           
 # [3] "M315, 80 L315, 80, 315, 82, 315, 83, 315, 84, 315, 85" "M315, 72 L315, 72"                                    
 # [5] "M315, 69 L315, 69, 315, 70"                            "M332, 66 L332, 66, 332, 67"                           
 # [7] "M315, 56 L315, 56"                                     "M315, 66 L315, 66, 315, 67"                           
 # [9] "M315, 72 L315, 72"                                     "M332, 72 L332, 72, 333, 75"                           
# [11] "M315, 72 L315, 72"                                     "M334, 73 L334, 73, 333, 73" 

Вы можете преобразовать всписок вектора строк с

ans <- 
  df %>%
    dplyr::mutate(dnodes = stringr::str_extract_all(xml_str, "(?<=[d]=')[^']+(?='\\/)")) %>%
    dplyr::mutate(dnodes = purrr::map(dnodes, ~unlist(strsplit(paste(.x, collapse=", "), ", "))))

ans$dnodes
# [[1]]
  # [1] "M171"     "160 L171" "160"      "168"      "159"      "164"      "159"      "163"      "159"      "162"     
 # [11] "159"      "161"      "159"      "161"      "158"      "162"      "158"      "162"      "157"      "163"     
 # [21] "156"      "165"      "156"      "M172"     "226 L172" "226"      "171"      "213"      "170"      "212"     
 # [31] "171"      "212"      "172"      "212"      "173"      "212"      "173"      "211"      "172"      "211"     
 # [41] "171"      "211"      "171"      "212"      "171"      "215"      "M153"     "94 L153"  "94"       "150"     
 # [51] "90"       "150"      "89"       "150"      "88"       "150"      "87"       "150"      "86"       "150"     
 # [61] "85"       "150"      "84"       "150"      "82"       "150"      "81"       "150"      "80"       "150" 
 # etc
...