Возвращает вектор из R dataframe

#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) временную переменную в лямбда-функции, чтобы генерировать данные дважды.