0

次の xml データを階層データ フレームに移動する作業を行っています。SOのヘルプのおかげで、xmlからすべてのデータを取得できました。ただし、現在、抽出したデータをクリーンアップして出力する前に整形する作業を行っています。これを何千回も行うためです。

更新: これは私が最終的に望んでいるものです。Timevaluefor をchannel動的に取得することはできないようです。ファイルごとにチャンネル名が変わります。

When channel = txt1[0](このファイルの場合txt1[0]="blah") ~ when 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>

昨日、私は SO でここに質問し、データ フレームに値timevalue値を取得する問題を解決しました: xml を pandas データ フレームに解析すると、メモリ エラーがスローされます

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) ごとにこのデータを出力して、データ セットの列としてチャネルを挿入できるようにしています。

そこで、チャネル名を動的に取得し、データを検索することにしました。このファイルには、9 つ​​の個別の有効なチャネル名がありますが、すべてのファイル (番号または名前) で同じではありません。

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), ...にそれらすべてを処理するために a を実行しました。しかし、空のデータ フレームを取得します。

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'):と、1 つの属性に対して出力されるようになりますが、参照を機能させることができませんtxt1[]

を参照して試してみました{0}..., txt1[]が、dchannel 属性のタプルを吐き出します (時間ノードの親である txt1 属性名を取得するのではなく、txt1 のすべてを取得しているためです。

XPath のドキュメントに目を通し、lxml チュートリアルを実行しましたが、動的検索が機能しない理由がわかりません。にフォールバックする必要があり.findall()ますか? この動的検索を使用して の各値のデータを取得するにはどうすればよいtxt1ですか?

[@name]おそらく、親の属性[@Time]、子の属性、そして孫のテキストを取得する関数を設定するなど、これにアプローチするより Pythonic な方法がありますが、valueその方法はまだわかりません。

4

1 に答える 1

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

わーい

于 2013-06-06T21:18:24.697 に答える