相当于DataFrame的Series.map?

时间:2014-03-10 06:44:32

标签: python pandas

Series.map与Series参数一起使用,我可以获取Series的元素并将它们用作另一个Series的索引。我想对DataFrame的一些列做同样的事情,将每一行作为一组索引级别用于MultiIndex-ed系列。这是一个例子:

>>> d = pandas.DataFrame([["A", 1], ["B", 2], ["C", 3]], columns=["X", "Y"])
>>> d
   X  Y
0  A  1
1  B  2
2  C  3

[3 rows x 2 columns]
>>> s = pandas.Series(np.arange(9), index=pandas.MultiIndex.from_product([["A", "B", "C"], [1, 2, 3]]))
>>> s
A  1    0
   2    1
   3    2
B  1    3
   2    4
   3    5
C  1    6
   2    7
   3    8
dtype: int32

我希望能够做d.map(s),以便d的每一行都应该被视为用于索引s的MultiIndex的元组。也就是说,我想要与此相同的结果:

>>> s.ix[[("A", 1), ("B", 2), ("C", 3)]]
A  1    0
B  2    4
C  3    8
dtype: int32

但是,与Series不同,DataFrame没有map方法。另一个明显的替代方法s.ix[d]给出了错误“无法使用多维键进行索引”,因此显然也不支持。

我知道我可以通过将DataFrame转换为列表列表,或者使用逐行apply来逐个抓取每个项目来实现,但如果没有任何方法可以做到这一点开销量是多少?如何一次在多个列上执行等效的Series.map

1 个答案:

答案 0 :(得分:2)

您可以使用以下方法从DataFrame和ix / loc创建MultiIndex:

In [11]: mi = pd.MultiIndex.from_arrays(d.values.T)

In [12]: s.loc[mi]  # can use ix too
Out[12]:
A  1    0
B  2    4
C  3    8
dtype: int64

这非常有效:

In [21]: s = pandas.Series(np.arange(1000*1000), index=pandas.MultiIndex.from_product([range(1000), range(1000)]))

In [22]: d = pandas.DataFrame(zip(range(1000), range(1000)), columns=["X", "Y"])

In [23]: %timeit mi = pd.MultiIndex.from_arrays(d.values.T); s.loc[mi]
100 loops, best of 3: 2.77 ms per loop

In [24]: %timeit s.apply(lambda x: x + 1)  # at least compared to apply
1 loops, best of 3: 3.14 s per loop