替换pandas DataFrame中的列值


141

我正在尝试替换数据框的一列中的值。列(“ female”)仅包含值“ female”和“ male”。

我尝试了以下方法:

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

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

理想情况下,我希望得到一些类似于下面的循环元素的输出。

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

我浏览了gotchas文档(http://pandas.pydata.org/pandas-docs/stable/gotchas.html),但无法弄清楚为什么什么也没发生。

任何帮助将不胜感激。

Answers:


259

如果我理解正确,则您需要以下内容:

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

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

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


6
谢谢。正是我想要的。如果我要将“女性”映射为1,将其他任何映射为“ 0”。那将如何工作?
黑色

17
如果map函数中指定了column中的所有值,则仅使用此函数。map函数中未指定的column值将被nan代替。
Chandra

1
我也建议使用.loc语法来避免SettingWithCopyWarningpandas.pydata.org/pandas-docs/stable/...
NickBraunagel

2
而不是.map我使用.replace
JS noob

我如何摆脱“。” 在两列或更多列上的数千个中,无法弄清楚。非常感谢
M. Mariscal

115

您可以使用loc编辑数据框的子集:

df.loc[<row selection>, <column selection>]

在这种情况下:

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

1
我将如何适应它,这样我就不需要通过条件选择特定的行,而只需选择特定列中的所有行?因此,将列中的所有单元格更改为特定值。
Dhruv Ghulati

3
@DhruvGhulati,您可以使用df.loc [:, <列选择>]


38

轻微变化:

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


11

您还可以使用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如果在字典中定义了数据框中列的所有可能值,则应使用字典,否则,对于未在字典中定义的列,该字段将为空。


8

这非常紧凑:

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)

第一个示例是链式索引,因此被警告,因为它不能保证结果df是副本还是视图。参见链式索引
编制-Nordle

7

另外,对于这些类型的分配,还有内置函数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)

然后,剩下两个新列,为您提供“ female”的伪编码,并且您摆脱了带有字符串的列。


4

使用Series.mapSeries.fillna

如果您的列包含的字符串多于femalemaleSeries.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

对于正确的方法,我们map与链接fillna,因此我们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

2

pandas调用了一个函数factorize,您可以使用该函数自动执行此类工作。它将标签转换为数字:['male', 'female', 'male'] -> [0, 1, 0]。有关更多信息,请参见此答案。


0

我认为应该指出,在上面建议的所有方法中,您都会得到哪种类型的对象:是Series还是DataFrame。

当您按w.female.或获得列w[[2]](假设其中2是列数)时,您将获得DataFrame。因此,在这种情况下,您可以使用DataFrame之类的方法.replace

当您使用.loc或者iloc你回来系列和系列没有.replace方法,所以你应该使用类似的方法applymap等等。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.