2017-06-12 51 views
0

我有成千上萬的XML文件,我試圖將其轉換爲R數據框。每個XML文件可能有不同的節點,每個節點的不同值,不同的結構等等,所以我試圖用一種不需要明確地輸出每個單獨文件的結構的方式來實現。但是,我無法將值分配給正確的標籤。將xml轉換爲數據框時分配給錯誤節點的值

假設我有文件中包含的以下XML命名爲「dat.xml」:

<?xml version="1.0" encoding="UTF-8"?> 
<HH_V2 id="HH_V2"> 
    <start>2017-01-30T11:31:56.811Z</start> 
    <end>2017-01-30T12:08:19.489Z</end> 
    <today>2017-01-30</today> 
    <deviceid>351569060022943</deviceid> 
    <time_st>2017-01-30</time_st> 
    <int_name>21</int_name> 
    <superv>4</superv> 
    <region>2</region> 
    <new_ea_flag>0</new_ea_flag> 
    <unique_id>c3d5c37d-b5c6-4b9d-a922-3b4f5be0e5ac</unique_id> 
    <village>Boana</village> 
    <hh_serial>71710003101</hh_serial> 
    <hh_serial2>71710003101</hh_serial2> 
    <id_consent> 
     <iconsent> 
      <iconsentlong /> 
     </iconsent> 
     <consent>1</consent> 
    </id_consent> 
     <meta> 
     <instanceID>uuid:ff93ead6-77b3-4c14-be7c-cbeb520ce0d7</instanceID> 
    </meta> 
</HH_V2> 

使用上面的XML文件,下面的腳本,我的數據幀包含一個名爲「元」與值列UUID:ff93ead6-77b3-4c14-be7c-cbeb520ce0d7。然而,我期待/希望它包含一個名爲「instanceID」的列,該列具有相同的值,基於後一個標記立即圍繞該值的事實。這通常發生在其他嵌套節點上。有沒有人有什麼建議?

# Load packages 
library(dplyr) 
library(XML) 

# Convert xml file to list of lists 
temp_list <- "dat.xml" %>% XML::xmlParse() %>% XML::xmlToList() 

# Unlist and store content as a single column with row 
# names for each variable in that node and the value of 
# the variable in a single column. 
for (j in 1:length(temp_list)) { 
    temp_list[[j]] <- temp_list[[j]] %>% unlist(recursive = TRUE) %>% 
    as.data.frame(stringsAsFactors = FALSE) 
    } 

# Each file is now a list of data frames comprised of 
# 1 column of values and row names for each variable. So 
# we bind these in order of their appearance in the list 
# of data frames 
temp_list <- do.call(rbind, temp_list) 

# Since we want each row to be a column and each column 
# to be a variable ('wide' format), we transpose the 
# dataframe to produce a single row for each instance 
# of the submitted form 
t(temp_list) %>% as.data.frame(stringsAsFactors = FALSE) 
+0

'as.data.frame(as.list(unlist(temp_list,recursive = TRUE)),stringsAsFactors = FALSE )'(在你未修改的'temp_list'上)做到這一點?小小的不便:一切都轉換爲字符,並且名稱以父節點名稱爲前綴,例如'「meta.instanceID」'您想要的地方''instanceID「' –

+0

適用於玩具數據集,稍後對完整數據進行測試。小心解釋爲什麼這與我的代碼相比起作用?不便之處很好(沒有petiods''),並且可以保留子字符串。 – user3614648

回答

0

temp_list <- "dat.xml" %>% XML::xmlParse() %>% XML::xmlToList()後,我建議簡單的代碼:

as.data.frame(as.list(unlist(temp_list, recursive = TRUE)), stringsAsFactors = FALSE) 

#      start      end  today  deviceid time_st int_name superv region new_ea_flag       unique_id village hh_serial hh_serial2 id_consent.consent       meta.instanceID .attrs.id 
# 1 2017-01-30T11:31:56.811Z 2017-01-30T12:08:19.489Z 2017-01-30 351569060022943 2017-01-30  21  4  2   0 c3d5c37d-b5c6-4b9d-a922-3b4f5be0e5ac Boana 71710003101 71710003101     1 uuid:ff93ead6-77b3-4c14-be7c-cbeb520ce0d7  HH_V2 

unlistrecursive = TRUE拉平整個列表,以一個矢量(與數字組成隱式轉換(編輯字符向量:只注意到一切已經是字符了,xmlParse沒有做任何自動類歸屬),所以要小心轉換回來,如果你需要那些作爲integerdouble)。默認use.names = TRUE將嵌套列表中的名稱與一個點連接起來,爲您提供名稱,如id_consent.consentmeta.instanceID

然後as.data.frame(as.list())使它成爲一行數據幀。

與你的代碼的不同之處在於:for循環用1個觀察值x 1變量的單個數據框替換每個父節點,沒有rownames,因此失去了嵌套名稱,僅保留父節點的最「外部」名稱。然後rbind將它們堆疊在一起,並且這些名稱在結果數據框中用作rownames。 t()將其轉換回字符矩陣! (使用現在用作colname的名稱)。最後,as.data.frame將其重新轉換回數據幀。這是很多不必要的步驟。我的解決方案也許有一些(unlist()然後as.list() ;-) ...但略少;-)

相關問題