【问题标题】:Update Value in one column, if string in other column contains something in list如果另一列中的字符串包含列表中的内容,则更新一列中的值
【发布时间】:2019-02-18 07:16:32
【问题描述】:
  id name             gender
0 13 John Smith       0
1 46 Jim Jeffries     2
2 75 Jennifer Johnson 0
3 37 Sam Adams        0
4 24 John Cleese      0
5 17 Taika Waititi    0

我的 df 中有很多人的姓名和性别,取自电影演员的数据库。性别被指定为 1(女性)、2(男性)或 0(未列出)。我想梳理一下并无情地按名字假设性别。名称将存储在列表中,并手动填写。也许我通过 ID 发现了一个具有性别非特定名称的人,并找出他们是男性/女性,我也想注入它:

m_names = ['John', ...]
f_names = ['Jennifer', ...]
m_ids   = ['37', ...]
f_ids   = ['', ...]

我已经很好地控制了 for 循环和 np.where,但我不知道如何逐行通过这个 df。

如果要使用上面的内容,我想要返回的内容如下:

for index, row in df.iterrows():
  if row['gender'] == 0:
    if   row['name'].str.contains(' |'.join(f_names)) or row['id'].str.contains('|'.join(f_ids)):
      return 1
    elif row['name'].str.contains(' |'.join(m_names)) or row['id'].str.contains('|'.join(m_ids)):
      return 2
print(df)

  id name             gender
0 13 John Smith       2
1 46 Jim Jeffries     2
2 75 Jennifer Johnson 1
3 37 Sam Adams        2
4 24 John Cleese      2
5 17 Taika Waititi    0

注意“|”前的空格在名字的条件中,避免抓住姓氏的任何部分。

此时,我遇到了如何格式化 if 语句的问题。 Python 不喜欢我的格式,并说我的“返回”是“外部函数”。如果我将这些更改为

row['gender'] = #

我遇到了 unicode 问题以及我对“str”和“contains”的使用。

【问题讨论】:

    标签: python pandas replace iteration conditional


    【解决方案1】:

    你可以使用 Pandas 函数

    https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.isin.html

    df.loc[df.name.isin(m_names), 'gender'] = 2
    

    【讨论】:

      【解决方案2】:

      好像你需要 np.select 并且没有 for 循环

      df['gender'] = np.select([df.name.str.contains(" |".join(m_names)),
                                df.name.str.contains(" |".join(f_names))],
                               [2, 1], 
                               default=3)
      

      【讨论】:

      • 编辑:我误读了我的读数并查看了“之前”的 df。它在没有任何其他条件语句的情况下工作!谢谢你。我明白我错过了什么。
      【解决方案3】:

      您可以先构造和组合布尔掩码。例如:

      m_zero = df['gender'].eq(0)
      
      m_name_female = df['name'].str.contains(' |'.join(f_names))
      m_name_male = df['name'].str.contains(' |'.join(m_names))
      
      m_id_female = df['id'].str.contains('|'.join(f_ids))
      m_id_male = df['id'].str.contains('|'.join(m_ids))
      
      female_mask = m_zero & (m_name_female | m_id_female)
      male_mask = m_zero & (m_name_male | m_id_male)
      

      然后通过pd.DataFrame.loc应用逻辑:

      df.loc[female_mask, 'gender'] = 1
      df.loc[male_mask, 'gender'] = 2
      

      或者使用嵌套的numpy.where:

      df['gender'] = np.where(female_mask, 1, np.where(male_mask, 2, df['gender']))
      

      或者,如果您希望提供标量默认值,请使用numpy.select

      df['gender'] = np.select([female_mask, male_mask], [1, 2], 3)
      

      【讨论】:

        猜你喜欢
        • 2018-05-21
        • 1970-01-01
        • 2018-12-05
        • 1970-01-01
        • 1970-01-01
        • 2022-11-12
        • 1970-01-01
        • 2015-08-19
        • 2021-07-04
        相关资源
        最近更新 更多