2017-06-12 3 views
0

私はRデータフレームに変換しようとしている何万ものXMLファイルを持っています。それぞれのXMLファイルは、異なるノード、各ノードの異なる値、異なる構造などを持つ可能性があります。そのため、個々のファイルの構造を明示的に入力する必要はありません。しかし、正しいタグに値を割り当てることができません。xmlをデータフレームに変換するときに不正なノードに割り当てられる値

私は「dat.xml」という名前のファイルに含まれる以下のXMLがあるとします。

上記の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> 

を、私のデータフレームは、値を持つ「メタ」という名前の列が含まれていますuuid:ff93ead6-77b3-4c14-be7c-cbeb520ce0d7。しかし、私は、後者のタグがすぐに値を取り囲んでいるという事実に基づいて、その同じ値を持つ "instanceID"という名前の列を含むことを期待していました。これは一般に他のネストされたノードで発生します。誰にも何か提案はありますか? temp_list <- "dat.xml" %>% XML::xmlParse() %>% XML::xmlToList()

# 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(aslist(temp_list、recursive = TRUE))、stringsAsFactors = FALSE ) '(あなたの変更されていない' temp_list'で)それをしますか?マイナーな不便さ:すべてが文字に変換され、名前に親ノード名が接頭辞として付けられます。例えば、 "" instanceID "' instanceID "のような名前です。 –

+0

玩具のデータセットで動作し、後で完全なデータでテストします。なぜ私のコードと比較してこれがうまくいくのかを説明する気に?不便はうまくいきます(列名にpetiodsはありません)。 – user3614648

答えて

0

私はシンプルなコード勧め:ちょうどすべてがあったことに気づい:recursive = TRUE

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 

unlistをベクトル(数値の暗黙的な変換と文字ベクトル(エディットにリスト全体を平坦化とにかく既に文字。xmlParseは自動クラス属性を使用していません)のように、integerまたはdoubleのように必要な場合は、戻って変換するように注意してください。デフォルトのuse.names = TRUEはネストされたリストの名前をドットで連結し、id_consent.consentmeta.instanceIDなどの名前を付けます。

as.data.frame(as.list())は、それを1行のデータフレームにします。

あなたのコードとの違いは、forループは各親ノードを1観測x 1変数の単一データフレームで置き換えます。rownamesはなく、したがってネストされた名前は失われ、親ノードの最も外側の名前のみが保持されます。その後、rbindを一緒に積み重ねると、それらの名前は、結果のデータフレームにrownamesとして機能します。 t()はそれを文字マトリックスに戻します! (名前は現在コルネームとして使用されています)。最後に、as.data.frameを再びデータフレームに戻します。これは多くの不必要なステップです。私の解決策にもいくつかあるかもしれません(unlist()次にas.list() ;-) ...わずかに少なく;-)

関連する問題