#r #xml #dataframe
#r #xml #dataframe
Вопрос:
Я довольно новичок в программировании на R, и у меня есть довольно простой вопрос.
Я загрузил следующий XML-документ в dataframe http://www.xmldatasets.net/temp/179681356453762.xml использование библиотеки XML. Мой вопрос в том, как я мог бы создать функцию, которая возвращала бы имя сенатора с учетом его / ее состояния?
т.е. что-то вроде senatorName (состояние), где возвращаемое значение будет вектором сенатора (ов) этого состояния.
Комментарии:
1. XML — это своего рода проблема, но Sunlight Foundation публикует ту же информацию, что и CSV (или API, если хотите). Вы можете захватить его напрямую с помощью just
congress <- read.csv('http://unitedstates.sunlightfoundation.com/legislators/legislators.csv')
, а затем обычным подмножеством, напримерcongress[congress$title == 'Sen' amp; congress$state == 'CA', 1:5]
Ответ №1:
XML — это своего рода проблема, но Sunlight Foundation публикует ту же информацию, что и CSV (или API, если хотите). Вы можете получить его напрямую, просто
congress <- read.csv('http://unitedstates.sunlightfoundation.com/legislators/legislators.csv')
а затем подмножьте его обычным образом или создайте функцию для этого:
find_senators <- function(state){
sens <- congress[congress$title == 'Sen' amp;
congress$state == state amp;
congress$in_office == 1, 1:5]
unname(apply(sens, 1, function(x){paste(x[x != ''], collapse = ' ')}))
}
find_senators("CA")
## [1] "Sen Barbara Boxer" "Sen Dianne Feinstein"
find_senators("IL")
## [1] "Sen Richard J. Durbin" "Sen Mark Steven Kirk"
Ответ №2:
Может быть, что-то вроде этого?
library(XML)
tg<-xmlToDataFrame("http://www.xmldatasets.net/temp/179681356453762.xml")
mt<-data.frame(fname=cbind(apply(tg[,2:3],1,function(x) paste0(x,collapse=", "))),state=tg$state)
mt[mt$state=="TX",]
fname state
28 Cornyn, John TX
43 Hutchison, Kay Bailey TX
Как указано ниже, если вы не хотите сворачивать фамилию и имя в один столбец, вы можете просто взять преобразованную XML-таблицу, tg
, и ввести:
tg[tg$state=="TX",]
Чтобы получить всю информацию о сенаторах в Техасе. И если вам нужно только имя и состояние, вы можете подмножить его как:
tg[tg$state=="TX",c(2:3,5)]
Если вы хотите иметь возможность вводить имя состояния в консоли и получать имя и состояния:
for (j in unique(tg$state)){
assign(j,tg[tg$state==j,c(2,3,5)])
}
А затем введите имя состояния, например MT
, и получите результат:
> MT
last_name first_name state
5 Baucus Max MT
89 Tester Jon MT
И вы также можете сделать функцию из этого:
senatorName<-function (x) tg[which(tg$state==paste0(x)),c(2:3,5)];
> senatorName("TX")
last_name first_name state
28 Cornyn John TX
43 Hutchison Kay Bailey TX
Комментарии:
1. Это близко к тому, что мне нужно. Хотя я не понимаю, что делает эта длинная средняя строка кода, мне это нужно как функция, где я могу ввести сокращение состояния. В отличие от жестко запрограммированного, как вы это сделали.
2. Пожалуйста, уточните. То, что вы говорите, довольно двусмысленно. Длинная строка кода — это просто свернуть фамилию и имя в один столбец. Однако вы могли бы просто сделать это и все будет в порядке: tg[tg $state==»TX»,] @KyleWeise
3. В вашем примере вы жестко запрограммировали «TX» в качестве состояния. Мне это нужно в терминах функции, где я могу ввести сокращение состояния. (.ie. TX или HI или CT) и возвращает соответствующие сенаторы
4. В примере about вы можете написать любое состояние, которое хотите. Измените «TX» на «HI» или «CT», и он будет работать. Если вы хотите иметь возможность вводить имя состояния в консоли и получать имя и состояния, см. Обновленный ответ выше. @KyleWeise
5. Я думаю, вы неправильно поняли мой вопрос. Мне нужно написать функцию . Мне нужно иметь возможность написать: senatorName(TX) и вернуть имена сенаторов.
Ответ №3:
Самое время начать развивать хорошие привычки:
library(xml2)
library(purrr)
library(dplyr)
doc <- read_xml("http://www.senate.gov/general/contact_information/senators_cfm.xml")
xml_find_all(doc, ".//member") %>%
map_df(function(x) {
set_names(xml_text(xml_children(x)), xml_name(xml_children(x))) %>%
as.list()
}) -> senators
senator_name <- function(df, x) {
filter(df, state==x) %>%
mutate(senator=sprintf("%s %s", first_name, last_name)) %>%
select(senator) %>%
flatten_chr()
}
senator_name(senators, "TX")
XML на самом деле не так уж и болезнен, и вы, к сожалению, столкнетесь с этим довольно часто, поэтому стоит немного попрактиковаться, IMO.
Использование dplyr
идиом поможет вам мыслить в терминах операций, которые вы хотите выполнить, и меньше полагаться на синтаксис подмножеств. Такой синтаксис хорош, но когда вы начнете выполнять больше аналитических работ в R, вы будете рады, что узнали dplyr
.
Вы также должны привыкнуть передавать данные и параметры для работы с / с. Копирование не выполняется до внесения изменений, и таким образом вы не полагаетесь на глобальные объекты.
Для больших наборов данных или повторяющихся операций я бы назначил xml_children(x)
временную переменную в лямбда-функции, чтобы генерировать данные дважды.