2013-06-05 33 views
0

我正在努力將nexted xml數據移動到分層數據框架中。由於SO的幫助,我能夠從xml中獲取所有數據。但是,現在,我正在努力清理在提取輸出之前提取並形成的數據,因爲我將這樣做數千次。在python中使用lxml和xpath通過xml屬性進行動態搜索

更新:這是我事實上想要的。我似乎無法動態獲取Timevaluechannel。頻道名稱將隨每個文件而改變。

channel = txt1[0](此文件,txt1[0]="blah")通過時channel = txt1[8](這個文件,txt1[8]="lir"

channel  Time     value 
0  blah  2013-05-01 00:00:00 258 
1  blah  2013-05-01 00:01:00 259 
... 
n-2 lir  2013-05-01 23:57:00 58 
n-1 lir  2013-05-01 23:58:00 37 
n  lir  2013-05-01 23:59:00 32 

這裏是我的xml文件是如何獲取和結構化:

import requests 
from lxml import etree, objectify 
r = requests.get('https://api.stuff.us/place/getData? security_key=key&period=minutes&startTime=2013-05-01T00:00&endTime=2013-05-01T23:59&sort=channel') #edited for privacy 
root = etree.fromstring(r.text) 
xml_new = etree.tostring(root, pretty_print=True) 
print xml_new[300:900] #gives xml output to show structure 
<startTime>2013-05-01 00:00:00</startTime> 
<endTime>2013-05-01 23:59:00</endTime> 
<summaryPeriod>minutes</summaryPeriod> 
<data> 
    <channel channel="97925" name="blah"> 
    <Time Time="2013-05-01 00:00:00"> 
     <value>258</value> 
    </Time> 
    <Time Time="2013-05-01 00:01:00"> 
     <value>259</value> 
    </Time> 
    <Time Time="2013-05-01 00:02:00"> 
     <value>258</value> 
    </Time> 
    <Time Time="2013-05-01 00:03:00"> 
     <value>257</value> 
    </Time> 

昨天,我在這裏問了這個問題,並解決了將數據幀中的值和timevalue合併成一個數據幀的問題:Parsing xml to pandas data frame throws memory error

dTime=[] 
dvalue=[] 
for df in root.xpath('//channel/Time'): 
    ## Iterate over attributes of Time but Time only has one attrib [@Time] 
    for attrib in df.attrib: 
    dTime.append(df.attrib[attrib]) 
    ## value is a child of time, and iterate 
    subfields = df.getchildren() 
    for subfield in subfields: 
    dvalue.append(subfield.text) 
pef=DataFrame({'Time':dTime,'values':dvalue}) 

pef 

&ltclass 'pandas.core.frame.DataFrame'&gt 
Int64Index: 12960 entries, 0 to 12959 
Data columns (total 2 columns): 
Time  12960 non-null values 
value 12960 non-null values 
dtypes: object(2) 

pef[:5] 

    Time     value 
0 2013-05-01 00:00:00 258 
1 2013-05-01 00:01:00 259 
2 2013-05-01 00:02:00 258 
3 2013-05-01 00:03:00 257 
4 2013-05-01 00:04:00 257 

現在,我正在給這個數據輸出爲每個信道的(結構是channel - >Time - >value)分開,這樣我可以插入信道作爲數據集的一列。

因此,我決定動態獲取通道名稱,並搜索數據。對於此文件,有九個獨立的有效通道名稱,但對於所有文件(數字或名稱)不同。

txt1 = root.xpath('//channel/@name') #this prints all channel names! 
len(txt1) 
Out[67]: 9 
print txt1 
['blah', 'b', 'c', 'd', 'vd', 'ef', 'fg', 'kc', 'lir'] 

我想我可以動態地獲取數據(使用較早的解決方案,但增加@name=txt1[0]),並最終做了for i = 0 to len(txt1), ...要經過所有的人。但是,我得到一個空的數據幀:

dTime=[] 
dchannel = txt1[0] # can hardcode, but need to be able to get all 
dvalue=[] 
for df in root.xpath('//channel[@name=txt1[0]]/Time'): 
    #CODE NEEDED: to get dchannel to dynamically = channel[@name] 
    ## Iterate over attributes of time for specific channel 
    for attrib in df.attrib: 
    dTime.append(df.attrib[attrib]) 
    ## value is a child of time, and iterate 
    subfields = df.getchildren() 
    for subfield in subfields: 
    dvalue.append(subfield.text) 
perf=DataFrame({'Channel': dchannel,'Time':dTime,'values':dvalue}) 

perf 

Int64Index([], dtype=int64) 
Empty DataFrame 

如果我硬編碼所需的屬性,就像for df in root.xpath('/*/*/*/channel[@name="blah"]/Time'):它將打印一個屬性,但我不能讓它工作參考txt1[]

我試圖參照{0}..., txt1[]但隨後吐出來了D信道屬性的元組(因爲它是讓所有txt1中,而不是獲取txt1中屬性名稱是時間節點的父節點。

我查看了XPath文檔,並且我已經通過了lxml教程,並且我無法弄清楚爲什麼我的動態搜索不起作用。我是否需要回退到.findall()?如何使用此動態搜索來獲取每個數據值在txt1

有可能是一個更pythonic的方法來解決這個問題,如設置一個函數,獲取attr ibute [@name]的父母,屬性[@Time]的孩子,然後孫子的文字value,但我還沒有想出如何做到這一點呢。

回答

0

好的,我解決了這個問題 - 但解決方案仍然很難看。

我很高興能想出來得到我想要的輸出。如果有人有一個更清潔的方法,我會很樂意看到它。謝謝。

dTime=[] 
dchannel = [] 
dvalue=[] 
for df in root.xpath('//channel/Time'): 
    dchannel.append(df.getparent().attrib['name']) 
    ## Iterate over attributes of time for specific channel 
    for attrib in df.attrib: 
    dTime.append(df.attrib[attrib]) 
    ## value is a child of time, and iterate 
    subfields = df.getchildren() 
    for subfield in subfields: 
    dvalue.append(subfield.text) 
perf=DataFrame({'Channel': dchannel,'Time':dTime,'values':dvalue}) 

perf[:2] 
    Channel  Time     value 
0 blah  2013-05-01 00:00:00 258 
1 blah  2013-05-01 00:01:00 259 
2 blah  2013-05-01 00:02:00 258 

perf[12957:12960] 
    Channel  Time     value 
12957 lir  2013-05-01 00:00:00 67 
12958 lir  2013-05-01 00:01:00 67 
12959 lir  2013-05-01 00:02:00 66 

YAY