是否等效于Series.map for DataFrame?

Bre*_*arn 5 python pandas

通过使用Series.mapSeries参数,我可以获取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
Run Code Online (Sandbox Code Playgroud)

我想做的是d.map(s),因此每行d都应作为一个元组,用于索引的MultiIndex s。也就是说,我想要与此相同的结果:

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

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

我知道我可以通过将DataFrame转换为列表列表,或通过逐行apply抓取每个项目来做到这一点,但是没有那么多的开销没有办法吗?我如何Series.map一次等效于多个列?

And*_*den 2

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

\n\n
In [11]: mi = pd.MultiIndex.from_arrays(d.values.T)\n\nIn [12]: s.loc[mi]  #\xc2\xa0can use ix too\nOut[12]:\nA  1    0\nB  2    4\nC  3    8\ndtype: int64\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是非常有效的:

\n\n
In [21]: s = pandas.Series(np.arange(1000*1000), index=pandas.MultiIndex.from_product([range(1000), range(1000)]))\n\nIn [22]: d = pandas.DataFrame(zip(range(1000), range(1000)), columns=["X", "Y"])\n\nIn [23]: %timeit mi = pd.MultiIndex.from_arrays(d.values.T); s.loc[mi]\n100 loops, best of 3: 2.77 ms per loop\n\nIn [24]: %timeit s.apply(lambda x: x + 1)  # at least compared to apply\n1 loops, best of 3: 3.14 s per loop\n
Run Code Online (Sandbox Code Playgroud)\n