【问题标题】:Conditional replacement of NaN有条件地替换 NaN
【发布时间】:2018-08-28 18:53:21
【问题描述】:

这里是 Python 新手。我希望我的问题不是完全多余的——如果是,请告诉我并将其归咎于我对 StackOverflow 的缺乏经验。

无论如何,我正在使用来自 kaggle.com 的 Titanic 数据集,并且我希望使用一组条件语句来替换整个数据框 Age 列中的 NaN“值”。最终,我想根据以下条件生成结果: 1)如果age==NaN,并且Title==(X or Y or Z),生成一个0-18范围内的随机数 2)如果age==NaN,并且Title==(A or B or C),生成19-80范围内的随机数

注意:'Title' 是列有个人标题的列(即先生、夫人、勋爵等)

我发现了类似的情况here,但我无法根据我的情况调整它,因为它根本不具备条件性。

这是我最近的尝试(根据本次更新的回复)

尝试 1

import random

mask_young = (df.Age.isnull()) & (df.Title.isin(Title_Young)) 
df.loc[mask_young, 'Age'] = df.loc[mask_young, 'Age'].apply(lambda x: np.random.randint(0,18))

mask_old = (df.Age.isnull()) & (df.Title.isin(Title_Old)) 
df.loc[mask_old, 'Age'] = df.loc[mask_old, 'Age'].apply(lambda x: np.random.randint(18,65))

mask_all = (df.Age.isnull()) & (df.Title.isin(Title_All)) 
df.loc[mask_all, 'Age'] = df.loc[mask_all, 'Age'].apply(lambda x: np.random.randint(0,65))

结果没有错误,但没有更正 'Age' 列中的 NaN 值

【问题讨论】:

  • 你的第一次尝试是遍历一个字符串,我想你的意思是for age in df['Age']: 。但更重要的是,当使用 pandas 时,这种情况下不需要循环。
  • 感谢您的提示,@pshep123。我已经考虑到了这一点(参见上面编辑过的代码),但是,它没有提供预期的结果。

标签: python python-3.x pandas dataframe conditional


【解决方案1】:

您想屏蔽您的 DataFrame,然后仅对与您的条件匹配的 DataFrame 部分执行操作。

import numpy as np
import pandas as pd

mask1 = (df.Age.isnull()) & (df.Title == 'Master')
df.loc[mask1, 'Age'] = df.loc[mask1, 'Age'].apply(lambda x: np.random.randint(0,18))

如果您确实需要在一个列表中包含多个标题的功能,这可以通过定义您关心的标题列表然后使用isin 来实现。例如:

list1 = ['Master', 'Sir', 'Mr']
mask1 = (df.Age.isnull()) & (df.Title.isin(list1))

【讨论】:

  • 感谢@ALollz - 这有帮助,我已经阅读了我遇到的一些错误,但代码没有达到预期的效果。 NaN 值仍然存在于 Age 列中。还有其他想法吗?
  • NaN 值是作为被 python 识别的实际空值读入的,还是只是字符串 'NaN'?使用df.dtypes 检查类型。否则可能在 Title 变量中有多余的空格,所以它们实际上是“先生”。这与“先生”不匹配。您可以通过使用df.loc[1,'Age'] 或任何您想要的索引和列选择单个元素的列和索引来查看它们的实际情况。
  • 感谢 ALollz!做到了。虽然在我来到论坛之前我确实有意识检查它们是字符串还是实际上是空值,但事实证明,我的一个列表没有你建议的标题前的空格。改变了那一件事,它就解决了这一切。谢谢!
猜你喜欢
  • 1970-01-01
  • 2018-11-29
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
相关资源
最近更新 更多