这里的场景是,我有一个包含原始整数数据的数据帧df
,以及一个将这些整数映射到字符串值的字典map_array
。
我需要将数据帧中的值替换为映射中的相应值,但如果它没有映射到任何内容,请保留原始值。
到目前为止,我能够弄清楚如何做我想做的事的唯一方法是使用临时列。 但是,由于我正在使用的数据大小,这有时会变得有点毛茸茸的。所以,我想知道是否有一些技巧可以在不需要临时列的情况下在熊猫中做到这一点......
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)
我认为您可以简单地使用.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
不过,我不确定更改列 dtype 的内存影响会是多少。
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)