有没有一种方法可以在原地执行Series.map,但如果没有匹配,则保留原始值?

14
这里的情境是我有一个包含原始整数数据的数据框df,以及一个将这些整数映射到字符串值的字典map_array。
我需要用地图中相应的值替换数据框中的值,但如果没有映射到任何值,则保留原始值。
到目前为止,我唯一能想到实现我的需求的方法是使用一个临时列。然而,由于我正在处理的数据规模较大,这可能会有点棘手。因此,我想知道是否有一些技巧可以在pandas中完成这个任务,而不需要临时列...
import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.randint(1,5, size=(100,1)))
map_array = {1:'one', 2:'two', 4:'four'}

df['__temp__'] = df[0].map(map_array, na_action=None) 
#I've tried varying the na_action arg to no effect

nan_index = data['__temp__'][df['__temp__'].isnull() == True].index
df['__temp__'].ix[nan_index] = df[0].ix[nan_index]
df[0] = df['__temp__']
df = df.drop(['__temp__'], axis=1)
2个回答

19

我认为你可以简单地使用 .replace,无论是在 DataFrame 还是 Series 上:

>>> df = pd.DataFrame(np.random.randint(1,5, size=(3,3)))
>>> df
   0  1  2
0  3  4  3
1  2  1  2
2  4  2  3
>>> map_array = {1:'one', 2:'two', 4:'four'}
>>> df.replace(map_array)
      0     1    2
0     3  four    3
1   two   one  two
2  four   two    3
>>> df.replace(map_array, inplace=True)
>>> df
      0     1    2
0     3  four    3
1   two   one  two
2  four   two    3

虽然我不确定更改列数据类型会对内存造成什么影响。


谢谢。更改列类型的命中是我需要采取的,所以没问题。 - badideas

2

map(或对于数据帧使用applymap)似乎更快。

诀窍是使用 lambda x: mapping.get(x, x) 作为映射,基本上默认情况下返回未更改的值。

df = pd.DataFrame(np.random.randint(1, 5, size=(100, 1000)))

mapping = {1: "one", 2: "two", 4: "four"}

res1 = df.replace(mapping)
res2 = df.applymap(lambda x: mapping.get(x, x))

pd.testing.assert_frame_equal(res1, res2)

>>> %timeit df.replace(mapping)
>>> %timeit df.applymap(lambda x: mapping.get(x, x))
175 ms ± 855 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
86.1 ms ± 725 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

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