Итак, если вы открыты для использования tidyverse
, вот подход. Сначала измените вашу функцию, чтобы извлечь все данные для отдельной записи:
library(tidyverse)
get_elements <- function(rec) {
name = xml_find_all(rec, "name") %>% xml_text
hobbies = xml_find_all(rec, "hobbies")
hobby_list = hobbies %>% xml_find_all("hobby") %>% xml_text
address = xml_find_all(rec, "address")
street = address %>% xml_find_all("street") %>% xml_text
street_num = address %>% xml_find_all("number") %>% xml_text
df = tibble(
name = str_squish(name),
street = str_squish(street),
street_num = str_squish(street_num),
hobbies = str_squish(hobby_list)
)
return(df)
}
Итак, теперь для любой данной записи (например, recs[1]
, recs[2]
) мы возвращаем таблицу:
get_elements(recs[1])
#> # A tibble: 2 x 4
#> name street street_num hobbies
#> <chr> <chr> <chr> <chr>
#> 1 John 2nd Av 1036 tennis
#> 2 John 2nd Av 1036 gardening
get_elements(recs[2])
#> # A tibble: 1 x 4
#> name street street_num hobbies
#> <chr> <chr> <chr> <chr>
#> 1 Mary 55th St 132 running
Затем скомбинируйте эти таблицы, используя ваш любимый метод:
res_df <-
bind_rows(
get_elements(recs[1]),
get_elements(recs[2])
)
# More tidyverse/purrr-like:
res_df <-
recs %>%
map_df(get_elements)
res_df
#> # A tibble: 3 x 4
#> name street street_num hobbies
#> <chr> <chr> <chr> <chr>
#> 1 John 2nd Av 1036 tennis
#> 2 John 2nd Av 1036 gardening
#> 3 Mary 55th St 132 running
Наконец, сделайте несколько обработок данных, чтобы повернуть данные в желаемый конечный формат:
res_df %>%
group_by(name) %>%
mutate(
hobby_idx = paste0("hobby", row_number())
) %>%
pivot_wider(
names_from = hobby_idx,
values_from = hobbies
)
#> # A tibble: 2 x 5
#> # Groups: name [2]
#> name street street_num hobby1 hobby2
#> <chr> <chr> <chr> <chr> <chr>
#> 1 John 2nd Av 1036 tennis gardening
#> 2 Mary 55th St 132 running <NA>