2015-06-09 3 views
1

Версии этого вопроса задавали раньше, как here и here. Тем не менее, я все еще не могу заставить его работать. Я пытаюсь проанализировать XML-документ в фрейме данных. Проблема в том, что некоторые из переменных не присутствуют для некоторых наблюдений, поэтому я получаю сообщение об ошибке, потому что существует другое количество строк. Мои данные выглядит следующим образом:XML к кадру данных с недостающими узлами

library("xml2") 
library("dplyr") 

example <- read_xml(
' 
<particDesc> 
<person role="participant" sameAs="#P484" xml:id="EDcon250_S1"> 
<age value="3">35-49</age> 
<sex value="1">male</sex> 
<occupation>waiter</occupation> 
<langKnowledge> 
<langKnown level="L1" tag="ita"/> 
</langKnowledge> 
</person> 
<person role="participant" sameAs="#P485" xml:id="EDcon250_S7"> 
<age value="0">unknown</age> 
<sex value="2">female</sex> 
<occupation>waitress</occupation> 
<langKnowledge> 
<langKnown level="L1" tag="ger-AT"/> 
</langKnowledge> 
</person> 
<person role="participant" sameAs="#P465" xml:id="EDcon250_S2"> 
<age value="2">25-34</age> 
<sex value="2">female</sex> 
<langKnowledge> 
<langKnown level="L1" tag="ger-AT"/> 
<langKnown level="L1" tag="eng-US"/> 
</langKnowledge> 
</person> 
</particDesc> 
') 

Я использую xml2 пакет Уикхема, чтобы прочитать XML. Я бы предпочел использовать этот пакет, но был бы открыт для использования XML, если это лучший (или единственный) способ решения этой проблемы. В любом случае, мой код выглядит следующим образом:

participants <- xml_find_all(example, './/person[@role = "participant"]') 

extract_participants <- function(div){ 
id <- xml_attr(div, "id") 
same_as <- xml_attr(div, "sameAs") 
role <- xml_attr(div, "role") 
age <- xml_find_all(div, ".//age") %>% xml_text() 
sex <- xml_find_all(div, ".//sex") %>% xml_text() 
occupation <- xml_find_all(div, ".//occupation") %>% xml_text() 

data_frame(id, same_as,role, age, sex, occupation) 
} 


parts_ls <- lapply(participants, extract_participants) 

participants_df <- do.call(rbind, parts_ls) 

Проблема в этом конкретных проблемах переменной occupation (третье лицо не имеет ни одного), но в моих реальных данных это может быть одна из других переменных, а также , Как я уже сказал, я вижу, что этот вопрос задавали раньше, но я мог бы получить какие-либо предложения для работы (возможно, из-за того, что я не понял понимания этого решения). В конце концов, я хотел бы Nas быть возвращены, когда конкретный узел отсутствует (так occupation переменная для третьего лица будет NA

На редактирования:. Вот альтернатива XML версия

library("XML") 
library("magrittr") 

example2 <- xmlParse(
' 
<particDesc> 
<person role="participant" sameAs="#P484" xml:id="EDcon250_S1"> 
<age value="3">35-49</age> 
<sex value="1">male</sex> 
<occupation>waiter</occupation> 
<langKnowledge> 
<langKnown level="L1" tag="ita"/> 
</langKnowledge> 
</person> 
<person role="participant" sameAs="#P485" xml:id="EDcon250_S7"> 
<age value="0">unknown</age> 
<sex value="2">female</sex> 
<occupation>waitress</occupation> 
<langKnowledge> 
<langKnown level="L1" tag="ger-AT"/> 
</langKnowledge> 
</person> 
<person role="participant" sameAs="#P465" xml:id="EDcon250_S2"> 
<age value="2">25-34</age> 
<sex value="2">female</sex> 
<langKnowledge> 
<langKnown level="L1" tag="ger-AT"/> 
<langKnown level="L1" tag="eng-US"/> 
</langKnowledge> 
</person> 
</particDesc> 
') 

example_root <- xmlRoot(example2) 

process <- function(x){ 
id <- xmlGetAttr(x, "id") 
role <- xmlGetAttr(x, "role") 
age <- getNodeSet(x, ".//age") %>% xmlSApply(xmlValue) 
sex <- getNodeSet(x, ".//sex") %>% xmlSApply(xmlValue) 
#occupation <- getNodeSet(x, ".//occupation") %>% xmlSApply(xmlValue) 
data.frame(id = id, 
      role = role, 
      #occupation = occupation, 
      age = age, 
      sex = sex, 
      stringsAsFactors = FALSE) 
} 


ls <- xpathApply(example_root, "//person", process) 
df <- do.call(rbind, ls) 

Просто раскомментируйте occupation.

ответ

1

У меня есть на что работать, но я не уверен, что это идеальное решение (я думаю, что это довольно длинный). В любом случае, вот что я до сих пор. для улучшения приветствуются.

library("XML") 
library("magrittr") 

example2 <- xmlParse(
' 
<particDesc> 
<person role="participant" sameAs="#P484" xml:id="EDcon250_S1"> 
<age value="3">35-49</age> 
<sex value="1">male</sex> 
<occupation>waiter</occupation> 
<langKnowledge> 
<langKnown level="L1" tag="ita"/> 
</langKnowledge> 
</person> 
<person role="participant" sameAs="#P485" xml:id="EDcon250_S7"> 
<age value="0">unknown</age> 
<sex value="2">female</sex> 
<occupation>waitress</occupation> 
<langKnowledge> 
<langKnown level="L1" tag="ger-AT"/> 
</langKnowledge> 
</person> 
<person role="participant" sameAs="#P465" xml:id="EDcon250_S2"> 
<age value="2">25-34</age> 
<sex value="2">female</sex> 
<langKnowledge> 
<langKnown level="L1" tag="ger-AT"/> 
<langKnown level="L1" tag="eng-US"/> 
</langKnowledge> 
</person> 
</particDesc> 
') 

example_root <- xmlRoot(example2) 
person <- getNodeSet(example_root, "//person") 

id <- lapply(person, xmlGetAttr, "id") %>% unlist() 
role <- lapply(person, xmlGetAttr, "role") %>% unlist() 
age <- lapply(person, xpathSApply, ".//age", xmlValue) %>% unlist() 
sex <- lapply(person, xpathSApply, ".//sex", xmlValue) %>% unlist() 
occupation <- lapply(person, xpathSApply, ".//occupation", xmlValue) 
occupation[sapply(occupation, is.list)] <- NA 
occupation <- unlist(occupation) 

df <- data.frame(
    id = id, 
    role = role, 
    age = age, 
    sex = sex, 
    occupation = occupation) 

На Edit: Для завершения, вот соответствующая xml2 версия (сокращенная)

example <- read_xml(
' 
<particDesc> 
<person role="participant" sameAs="#P484" xml:id="EDcon250_S1"> 
<age value="3">35-49</age> 
<sex value="1">male</sex> 
<occupation>waiter</occupation> 
<langKnowledge> 
<langKnown level="L1" tag="ita"/> 
</langKnowledge> 
</person> 
<person role="participant" sameAs="#P485" xml:id="EDcon250_S7"> 
<age value="0">unknown</age> 
<sex value="2">female</sex> 
<occupation>waitress</occupation> 
<langKnowledge> 
<langKnown level="L1" tag="ger-AT"/> 
</langKnowledge> 
</person> 
<person role="participant" sameAs="#P465" xml:id="EDcon250_S2"> 
<age value="2">25-34</age> 
<sex value="2">female</sex> 
<langKnowledge> 
<langKnown level="L1" tag="ger-AT"/> 
<langKnown level="L1" tag="eng-US"/> 
</langKnowledge> 
</person> 
</particDesc> 
') 

participants <- xml_find_all(example, './/person[@role = "participant"]') 

id <- lapply(participants, xml_attr, "id") 
occupation <- lapply(participants, xml_find_all, ".//occupation") 
occupation <- lapply(occupation, xml_text) 
occupation[!sapply(occupation, function(y) length(y == 0))] <- NA 

occupation <- unlist(occupation) 
id <- unlist(id) 

data_frame(
    id = id, 
    occupation = occupation) 
Смежные вопросы