Answers:
您可以使用.replace
。例如:
>>> df = pd.DataFrame({'col2': {0: 'a', 1: 2, 2: np.nan}, 'col1': {0: 'w', 1: 1, 2: 2}})
>>> di = {1: "A", 2: "B"}
>>> df
col1 col2
0 w a
1 1 2
2 2 NaN
>>> df.replace({"col1": di})
col1 col2
0 w a
1 A 2
2 B NaN
或直接在上Series
,即df["col1"].replace(di, inplace=True)
。
'3.6.1 |Anaconda custom (64-bit)| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)]'
map
可以比 replace
如果您的字典有多个键,使用map
速度可能比快得多replace
。此方法有两种版本,具体取决于字典是否详尽地映射所有可能的值(以及是否要让不匹配项保留其值或将其转换为NaN):
在这种情况下,表格非常简单:
df['col1'].map(di) # note: if the dictionary does not exhaustively map all
# entries then non-matched entries are changed to NaNs
尽管map
最常用函数作为参数,但也可以选择字典或系列: Pandas.series.map的文档
如果您有一个非详尽的映射,并且希望保留现有变量用于非匹配,则可以添加fillna
:
df['col1'].map(di).fillna(df['col1'])
如@jpp的答案在这里: 通过字典有效地替换熊猫系列中的值
在pandas 0.23.1版中使用以下数据:
di = {1: "A", 2: "B", 3: "C", 4: "D", 5: "E", 6: "F", 7: "G", 8: "H" }
df = pd.DataFrame({ 'col1': np.random.choice( range(1,9), 100000 ) })
并进行测试时%timeit
,它的map
速度大约比速度快10倍replace
。
请注意,您的加速map
会随数据而变化。最大的提速似乎是使用大词典和详尽的替换方法。有关更广泛的基准测试和讨论,请参见@jpp答案(上面链接)。
df.replace
功能虽然整洁且对小命令有用,但在运行20分钟左右后便崩溃了。
map
也适用于无法找到解决方案的索引replace
您的问题有点含糊。至少有三种解释:
di
引用索引值di
指df['col1']
值di
指的是索引位置(不是OP的问题,而是为了娱乐而抛出的。)以下是每种情况的解决方案。
情况1:
如果的键di
旨在引用索引值,则可以使用以下update
方法:
df['col1'].update(pd.Series(di))
例如,
import pandas as pd
import numpy as np
df = pd.DataFrame({'col1':['w', 10, 20],
'col2': ['a', 30, np.nan]},
index=[1,2,0])
# col1 col2
# 1 w a
# 2 10 30
# 0 20 NaN
di = {0: "A", 2: "B"}
# The value at the 0-index is mapped to 'A', the value at the 2-index is mapped to 'B'
df['col1'].update(pd.Series(di))
print(df)
产量
col1 col2
1 w a
2 B 30
0 A NaN
我已经修改了您原始帖子中的值,因此操作更清晰update
。注意输入中的键如何di
与索引值关联。索引值的顺序(即索引位置)无关紧要。
情况2:
如果其中的键di
引用df['col1']
值,则@DanAllan和@DSM显示如何通过以下方法实现此目的replace
:
import pandas as pd
import numpy as np
df = pd.DataFrame({'col1':['w', 10, 20],
'col2': ['a', 30, np.nan]},
index=[1,2,0])
print(df)
# col1 col2
# 1 w a
# 2 10 30
# 0 20 NaN
di = {10: "A", 20: "B"}
# The values 10 and 20 are replaced by 'A' and 'B'
df['col1'].replace(di, inplace=True)
print(df)
产量
col1 col2
1 w a
2 A 30
0 B NaN
注意如何在这种情况下,在键di
改为匹配值的df['col1']
。
情况3:
如果其中的键di
引用了索引位置,则可以使用
df['col1'].put(di.keys(), di.values())
以来
df = pd.DataFrame({'col1':['w', 10, 20],
'col2': ['a', 30, np.nan]},
index=[1,2,0])
di = {0: "A", 2: "B"}
# The values at the 0 and 2 index locations are replaced by 'A' and 'B'
df['col1'].put(di.keys(), di.values())
print(df)
产量
col1 col2
1 A a
2 10 30
0 B NaN
在这里,第一行和第三行被更改了,因为其中的键di
是0
和2
,使用Python基于0的索引对其进行索引,它们指向第一位置和第三位置。
replace
同样好,也许对于这里发生的事情来说是一个更好的词。
update()
与相比replace()
,似乎有点糊涂,但至少有效。
如果您有多个列要在数据数据帧中重新映射,则添加到此问题:
def remap(data,dict_labels):
"""
This function take in a dictionnary of labels : dict_labels
and replace the values (previously labelencode) into the string.
ex: dict_labels = {{'col1':{1:'A',2:'B'}}
"""
for field,values in dict_labels.items():
print("I am remapping %s"%field)
data.replace({field:values},inplace=True)
print("DONE")
return data
希望它对某人有用。
干杯
DataFrame.replace()
,尽管我不知道何时添加。
DSM已经接受了答案,但是编码似乎并不适合所有人。这是与当前版本的熊猫一起使用的版本(截至8/2018为0.23.4):
import pandas as pd
df = pd.DataFrame({'col1': [1, 2, 2, 3, 1],
'col2': ['negative', 'positive', 'neutral', 'neutral', 'positive']})
conversion_dict = {'negative': -1, 'neutral': 0, 'positive': 1}
df['converted_column'] = df['col2'].replace(conversion_dict)
print(df.head())
您会看到它看起来像:
col1 col2 converted_column
0 1 negative -1
1 2 positive 1
2 2 neutral 0
3 3 neutral 0
4 1 positive 1
Series.map()
似乎更灵活。
给定map
的速度比替换(@JohnE的解决方案)要快,因此在打算将特定值映射到的非穷举映射时,您NaN
需要格外小心。在这种情况下,正确的方法需要在您mask
使用Series时执行.fillna
,否则撤消到的映射NaN
。
import pandas as pd
import numpy as np
d = {'m': 'Male', 'f': 'Female', 'missing': np.NaN}
df = pd.DataFrame({'gender': ['m', 'f', 'missing', 'Male', 'U']})
keep_nan = [k for k,v in d.items() if pd.isnull(v)]
s = df['gender']
df['mapped'] = s.map(d).fillna(s.mask(s.isin(keep_nan)))
gender mapped
0 m Male
1 f Female
2 missing NaN
3 Male Male
4 U U
作为对Nico Coallier(适用于多列)和U10-Forward(使用应用方式的方法)的建议的扩展,并将其概括为一个单一的行:
df.loc[:,['col1','col2']].transform(lambda x: x.map(lambda x: {1: "A", 2: "B"}.get(x,x))
将.transform()
每个列按顺序处理。.apply()
与之相反,将DataFrame中聚集的列传递给该列。
因此,您可以应用Series方法map()
。
最后,由于U10,我发现了此行为,您可以在.get()表达式中使用整个Series。除非我误解了它的行为,并且它按顺序而不是按位处理序列。您在映射字典中未提及的值
的.get(x,x)
帐户,否则该.map()
方法将被视为Nan
.transform()
每个列按顺序处理。.apply()
与之相反,将DataFrame中聚合的列传递给该列。我刚刚尝试过,apply()
效果很好。都不需要使用loc
,这似乎过于复杂。df[["col1", "col2"]].apply(lambda col: col.map(lambda elem: my_dict.get(elem, elem)))
应该工作正常。该.get(x,x)
账户的价值观,你没有在这将被否则被视为楠你的映射字典提.map()
方法你也可以使用fillna()
之后。
一种更本地的熊猫方法是应用如下替换函数:
def multiple_replace(dict, text):
# Create a regular expression from the dictionary keys
regex = re.compile("(%s)" % "|".join(map(re.escape, dict.keys())))
# For each match, look-up corresponding value in dictionary
return regex.sub(lambda mo: dict[mo.string[mo.start():mo.end()]], text)
定义函数后,可以将其应用于数据框。
di = {1: "A", 2: "B"}
df['col1'] = df.apply(lambda row: multiple_replace(di, row['col1']), axis=1)
col```` is tuple. The error info is
不能比的类型“ndarray(D型=对象)”和“tuple'```