将dict中的列表转换为Series

时间:2013-04-02 16:47:41

标签: python python-3.x pandas

我正在尝试从HTML输入文件中读取行并准备Series / DataFrames,以便最终创建图形。我正在使用lxml的objectify来获取HTML数据并将它们转换为列表。每当我尝试获取列表数据并创建一个Series或DataFrame时,我得到一个Series(或DataFrame),其中包含的元素数量等于列表中的项目数,但元素的数据本身就是我的列表。 / p>

我能说明问题的最简单方法是:

from lxml import etree
from lxml import objectify
from pandas import Series
line='<tr class="alt"><td>192.168.1.0</td><td>XXDHCP</td><td>Y</td><td>255</td><td>0</td><td>YYDHCP</td><td>Y</td><td>250</td><td>0</td><td>0%</td><td>505</td><td>505</td><td>0</td><td></td></tr>'
htmldata=(objectify.fromstring(line)).getchildren()
htmlseries=Series(htmldata)

htmlseries最终看起来像:

0     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
1     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
2     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
3     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
4     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
5     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
6     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
7     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
8     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
9     [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
10    [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
11    [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
12    [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...
13    [[[192.168.1.0, XXDHCP, Y, 255, 0, YYDHCP, Y, ...

type(htmldata[0])是:lxml.objectify.StringElement
type(htmldata[3])是:lxml.objectify.IntElement

我正在寻找类似的东西:

0     192.168.1.0
1          XXDHCP
2               Y
3             255
4               0
5          YYDHCP
6               Y
7             250
8               0
9              0%
10            505
11            505
12              0
13               

我做错了什么?对于发生的事情,我有点神秘。当我尝试将每列读入列表时:

data=objectify.fromstring(line).getchildren()
labdata[ip]['Scope'].append(data[0])
labdata[ip]['Cluster1'].append(data[1])
labdata[ip]['Active1'].append(data[2])
...etc...

我的列表最终看起来像:

labdata['192.168.1.0']['Utilization']
['100%',
 '96%',
 '96%',
 '90%',
 '81%',
 '96%',
 '90%',
 '97%',
 '98%',
 '92%',
 '99%',
 ...etc...
 ]

但出于某种原因:

Series(labdata['192.168.1.0']['Utilization'])
0     [[[192.168.1.0, XXDHCP, Y, 0, 383, YYDHCP, Y...
1     [[[192.168.1.0, XXDHCP, Y, 28, 355, YYDHCP, ...
2     [[[192.168.1.0, XXDHCP, Y, 28, 355, YYDHCP, ...
3     [[[192.168.1.0, XXDHCP, Y, 76, 307, YYDHCP, ...
4     [[[192.168.1.0, XXDHCP, Y, 104, 279, YYDHCP,...
5     [[[192.168.1.0, XXDHCP, Y, 27, 356, YYDHCP, ...
6     [[[192.168.1.0, XXDHCP, Y, 66, 317, YYDHCP, ...
7     [[[192.168.1.0, XXDHCP, Y, 15, 368, YYDHCP, ...
8     [[[192.168.1.0, XXDHCP, Y, 15, 368, YYDHCP, ...
9     [[[192.168.1.0, XXDHCP, Y, 54, 329, YYDHCP, ...
...etc...

type(labdata['192.168.1.0']['Utilization'][0])lxml.objectify.StringElement

我是否需要将这些元素转换为普通字符串和整数?

2 个答案:

答案 0 :(得分:7)

问题是htmldata中的元素不是简单类型,而np.isscalar在这里被欺骗了 (因为这是确定我们是否有列表列表或标量列表的方式 只是字符串化元素是否可行

In [23]: print [ type(x) for x in htmldata ]
[<type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.StringElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.IntElement'>, <type 'lxml.objectify.StringElement'>]

In [24]: Series([ str(x) for x in htmldata ])
Out[24]: 
0     192.168.1.0
1          XXDHCP
2               Y
3             255
4               0
5          YYDHCP
6               Y
7             250
8               0
9              0%
10            505
11            505
12              0
13               

答案 1 :(得分:2)

好问题!这是奇怪的行为。

出现问题是因为您正在传递系列列表lxml.objectify.StringElementpandasnp.array支持,因此更喜欢将其数据存储在统一数组中。因此,它将所有内容抽象为np.object,以便它可以将它们推入数组中。实际上,如果你查看数据的基础数组(Series.values),你会看到它被创建得很好,虽然它是lxml.objectify.StringElements的一个numpy数组,可能不是你想要的。< / p>

简单的解决方案当然是将所有内容都转换为字符串,这可能就是你想要做的事情。


但是为什么打印有趣,你问?好吧,如果您在pandas中钻取代码,最终会得到pandas.core.common中的以下函数:

def _is_sequence(x):
    try:
        iter(x)
        len(x) # it has a length
        return not isinstance(x, basestring) and True
    except Exception:
        return False

换句话说,pandas看到lxml对象不是basetrings,因此假定它们是序列。熊猫应该检查isinstance(x, collections.Sequence) ...