DataFrame的Series.map等价方法是什么?

5 投票
1 回答
781 浏览
提问于 2025-04-17 21:35

使用 Series.map 方法时,如果我给它一个 Series 作为参数,它就能把这个 Series 的元素当作索引去查找另一个 Series 的值。我想用同样的方法来处理 DataFrame 的一些列,把每一行当作一组索引,去查找一个有多重索引的 Series。下面是一个例子:

>>> 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 的多重索引中查找对应的值。也就是说,我想要的结果和下面这个是一样的:

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

不过,DataFrame 和 Series 不一样,它没有 map 这个方法。另一个明显的选择 s.ix[d] 会报错“无法用多维键进行索引”,所以这显然也不支持。

我知道可以通过把 DataFrame 转换成一个列表的列表,或者使用逐行的 apply 方法来一个一个地抓取每个项目,但有没有什么方法可以避免这么大的开销呢?我该如何一次性对多个列做出类似于 Series.map 的操作呢?

1 个回答

2

你可以从数据表(DataFrame)创建一个多重索引(MultiIndex),然后使用 ix 或 loc 来进行操作:

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

撰写回答