替换列(字符串)中的值时无法覆盖现有的数据框值

时间:2018-06-22 10:57:30

标签: python string pandas dataframe

我在熊猫中有一个数据框,其中包含客户ID及其性别。但是,在清理数据集时,我注意到某些ID分配了两种性别,在大多数情况下是“女性”或“男性”,而“未知”。

df看起来像这样:

 index   ID    gender
   0     23      M
   1     23      U
   2     55      F
   3     55      U

我的目标是找到分配了两种性别的ID,并将U性别替换为非U性别。

为此,我在列表上使用了一个for循环,在该列表中,我具有所有性别不一致的客户ID。例如,对于ID = 23,循环内的代码如下所示:

if all((customers.loc[customers['ID'] == 23]['gender'].str.contains('M')) | (customers.loc[customers['ID'] == 23]['gender'].str.contains('U'))):
    customers.loc[customers['ID'] == 23]['gender'] = customers.loc[customers['ID'] == 23]['gender'].replace('U', 'M')

我的问题:

  1. 不确定for循环和if语句是否最适合执行我的任务
  2. 使用我的方法时,我无法覆盖现有数据框。我尝试使用replace(inplace = True),我尝试使用.loc()如上所述分配新性别,但也尝试使用链式索引。在所有情况下,我都会收到警告(使用.loc或链接索引时):

    A value is trying to be set on a copy of a slice from a DataFrame.
    Try using .loc[row_indexer,col_indexer] = value instead
    See the caveats in the documentation: http://pandas.pydata.org/pandas- 
    docs/stable/indexing.html#indexing-view-versus-copy
    

(在使用replace(inplace = True时)

    C:\Users\***: SettingWithCopyWarning: 
    A value is trying to be set on a copy of a slice from a DataFrame

并且原始数据框是完整的。

我对StackOverflow进行了广泛的研究,但仍然无法解决我的问题。

1 个答案:

答案 0 :(得分:1)

对于此任务,循环将效率很低。相反,您可以使用groupby。这是一种依靠排序的解决方案。

请注意,NaNM下方出现F

res = df.copy()

res['gender'] = res.replace('U', np.nan\
                   .sort_values('gender')\
                   .groupby('ID')['gender'].transform('first')\
                   .fillna('U')\
                   .sort_values('index')

print(res)

   index  ID gender
0      0  23      M
1      1  23      M
2      2  55      F
3      3  55      F

在这种特殊情况下,如@ pshep123所述,由于U按字母顺序显示在MF之后,因此您可以按组取最小值:

res['gender'] = res.groupby('ID')['gender'].transform('min')