将一个2维数组放入Pandas系列中

23

我有一个 2D 的 Numpy 数组,我想将它放在 pandas 的 Series 中(而不是 DataFrame):

>>> import pandas as pd
>>> import numpy as np
>>> a = np.zeros((5, 2))
>>> a
array([[ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.]])

但是这会引发一个错误:

>>> s = pd.Series(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/miniconda/envs/pyspark/lib/python3.4/site-packages/pandas/core/series.py", line 227, in __init__
    raise_cast_failure=True)
  File "/miniconda/envs/pyspark/lib/python3.4/site-packages/pandas/core/series.py", line 2920, in _sanitize_array
    raise Exception('Data must be 1-dimensional')
Exception: Data must be 1-dimensional

通过黑客手段是可能的:

>>> s = pd.Series(map(lambda x:[x], a)).apply(lambda x:x[0])
>>> s
0    [0.0, 0.0]
1    [0.0, 0.0]
2    [0.0, 0.0]
3    [0.0, 0.0]
4    [0.0, 0.0]

有更好的方法吗?


默认情况下,Pandas 获取 np 数组的形状并相应地分配 DataFrame。因此,您需要欺骗 np 数组的形状...这就是您的“hack”所做的事情,尽管是一次处理一行。 - Kartik
有没有想法如何使用矩阵操作将每一行包装在一个列表中? - zemekeneng
2
只是出于好奇,你为什么想要这个? - juanpa.arrivillaga
你可能想尝试元组。使用分隔符“:”的x:y,但请注意,当numpy在矩阵中看到对象时,将默认为“object”计算模式而不是“C”计算模式。 - Merlin
1
机器学习。我想将一个向量化的文本语料库附加到包含标签和其他特征的DataFrame中。这样可以更容易地过滤整个数据集,并且对于子集可能没有完整标签集的较小数据集特别方便。我希望所有列都在一个系列中,因为我不想为DataFrame中的每个词汇跟踪一列。如果您有更好的管理系统,请告诉我! - zemekeneng
2个回答

27

你可以使用 numpy.ndarray.tolist 函数,像这样:

>>> a = np.zeros((5,2))
>>> a
array([[ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.],
       [ 0.,  0.]])
>>> a.tolist()
[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]
>>> pd.Series(a.tolist())
0    [0.0, 0.0]
1    [0.0, 0.0]
2    [0.0, 0.0]
3    [0.0, 0.0]
4    [0.0, 0.0]
dtype: object

编辑:

实现类似结果的更快方法是仅执行pd.Series(list(a))。这将生成NumPy数组的系列,而不是Python列表,因此应该比返回Python列表的a.tolist更快。


谢谢,如果列数在25以下,那个更快,但是如果有几百或几千列,那个会慢很多。 - zemekeneng
4
我找到了另一种更快的方法。请看编辑后的答案。 - bpachev
很好,感谢您坚持下来!它在每种情况下都是最快的。 - zemekeneng

3
 pd.Series(list(a))

一直比其慢

pd.Series(a.tolist())

测试了 2000 万 -- 50 万行数据

a = np.ones((500000,2))

仅显示100万行:
%timeit pd.Series(list(a))
1 loop, best of 3: 301 ms per loop

%timeit pd.Series(a.tolist())
1 loop, best of 3: 261 ms per loop

1
当你只有两列时,这是正确的。试试几千列,看看会发生什么。 - bpachev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接