在pandas DataFrame中替换列值

222
我正在尝试替换数据框中一列的值。该列('female')只包含“female”和“male”这两个值。
我尝试了以下方法:
```python df['female'] = df['female'].replace({'female': 0, 'male': 1}) ```
请注意,上述代码将字符串“female”替换为数字0,“ male”替换为数字1。
w['female']['female']='1'
w['female']['male']='0' 

但是收到与先前结果完全相同的副本。

我希望得到一些输出,其元素逐个类似于以下循环。

if w['female'] =='female':
    w['female'] = '1';
else:
    w['female'] = '0';

我已经阅读了“陷阱”文档(http://pandas.pydata.org/pandas-docs/stable/gotchas.html),但无法弄清为什么没有任何反应。

任何帮助将不胜感激。

16个回答

360

如果我理解正确,您希望类似于这样的东西:

w['female'] = w['female'].map({'female': 1, 'male': 0})

这里我将值转换为数字而不是包含数字的字符串。 如果您真的想要,您可以将它们转换为"1""0",但我不确定为什么您要这样做。

您的代码之所以不起作用,是因为在列上使用['female'](在w['female']['female']中的第二个'female')并不意味着“选择值为'female'的行”。 它的意思是选择索引为“female”的行,而您的DataFrame中可能没有任何这样的行。


7
谢谢。正是我想要的。如果我把“女性”映射为1,其他任何东西映射为0,该怎么做呢? - Black
40
仅当列中的所有值都在映射函数中给出时才使用此选项。未在映射函数中指定的列值将被替换为NaN。 - Chandra
2
我还建议使用.loc语法来避免SettingWithCopyWarning警告:https://pandas.pydata.org/pandas-docs/stable/indexing.html#different-choices-for-indexing - NickBraunagel
3
我使用了.replace 而不是 .map。 - JS noob
这个解决方案可行,但您需要在列中指定所有的键。未指定的键将被赋予NaN值。 - cerebrou
显示剩余4条评论

149
您可以使用 loc 来编辑数据框的子集:
df.loc[<row selection>, <column selection>]

在这种情况下:

w.loc[w.female != 'female', 'female'] = 0
w.loc[w.female == 'female', 'female'] = 1

1
我该如何修改它,以便无需通过条件选择特定行,而是选择某一列中的所有行?将该列中的所有单元格更改为特定值。 - Dhruv Ghulati
4
你需要使用 df.loc[:, <列选择>],DhruvGhulati。 - user4322543

68

2
这是我遇到的问题的最佳解决方案,谢谢! - Andrew Brēza

55

稍微变化:

w.female.replace(['male', 'female'], [1, 0], inplace=True)

26

这也应该可以:

w.female[w.female == 'female'] = 1 
w.female[w.female == 'male']   = 0

18

这非常紧凑:

w['female'][w['female'] == 'female']=1
w['female'][w['female'] == 'male']=0

另一个好选择:

w['female'] = w['female'].replace(regex='female', value=1)
w['female'] = w['female'].replace(regex='male', value=0)

2
第一个例子是链式索引,不建议使用,因为它无法保证结果df是副本还是视图。请参见chained-indexing - Nordle

12
您也可以使用apply.get,例如: w['female'] = w['female'].apply({'male':0, 'female':1}.get)
w = pd.DataFrame({'female':['female','male','female']})
print(w)

数据框 w:
   female
0  female
1    male
2  female

使用apply从字典中替换值:
w['female'] = w['female'].apply({'male':0, 'female':1}.get)
print(w)

结果:

   female
0       1
1       0
2       1 

注意:如果数据框中的所有列的可能值都在字典中定义,则应使用带有字典的 apply,否则对于字典中未定义的值将为空。

10

使用 Series.fillnaSeries.map

如果您的列包含的字符串不仅仅是femalemale,那么在这种情况下使用Series.map将会失败,因为它会返回其他值的NaN

这就是为什么我们必须与fillna链式使用它的原因:

.map 失败示例:

df = pd.DataFrame({'female':['male', 'female', 'female', 'male', 'other', 'other']})

   female
0    male
1  female
2  female
3    male
4   other
5   other
df['female'].map({'female': '1', 'male': '0'})

0      0
1      1
2      1
3      0
4    NaN
5    NaN
Name: female, dtype: object

对于正确的方法,我们将mapfillna链接在一起,因此我们使用原始列中的值来填充NaN

df['female'].map({'female': '1', 'male': '0'}).fillna(df['female'])

0        0
1        1
2        1
3        0
4    other
5    other
Name: female, dtype: object

9

对于这类任务,还可以使用内置函数pd.get_dummies:

w['female'] = pd.get_dummies(w['female'],drop_first = True)

这将给你一个数据框,其中有两列,每个值出现在w [ 'female']中的一个,因此您会删除第一个 (因为您可以从留下的那一个推断出它)。新列会自动命名为您替换的字符串。
如果您的分类变量有多于两个可能值,则尤其有用。此函数创建所需的许多虚拟变量以区分所有情况。然后请注意不要将整个数据框分配给单个列,而是如果w [ 'female']可以是'male'、'female'或'neutral'之一,请执行以下操作:
w = pd.concat([w, pd.get_dummies(w['female'], drop_first = True)], axis = 1])
w.drop('female', axis = 1, inplace = True)

然后您会得到两个新的列,给出“女性”的虚拟编码,并消除了字符串的列。


9
w.replace({'female':{'female':1, 'male':0}}, inplace = True)

上述代码将仅在“female”列中将“female”替换为1,将“male”替换为0。

2
我并没有在原帖作者的情况下实际尝试过,但是对于 inplace 给予加分。 - James Hirschorn
在我的情况下,它是用于可链接表达式的a + 1,而不是用于"inplace"! - endive1783

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