【问题标题】:Replace specific value in pandas dataframe column, else convert column to numeric替换熊猫数据框列中的特定值,否则将列转换为数字
【发布时间】:2019-08-18 09:50:13
【问题描述】:

鉴于以下熊猫数据框

+----+------------------+-------------------------------------+--------------------------------+
|    |   AgeAt_X        |   AgeAt_Y                           |   AgeAt_Z                      |
|----+------------------+-------------------------------------+--------------------------------+
|  0 |   Older than 100 |                      Older than 100 |                          74.13 |
|  1 |              nan |                                 nan |                          58.46 |
|  2 |              nan |                                 8.4 |                          54.15 |
|  3 |              nan |                                 nan |                          57.04 |
|  4 |              nan |                               57.04 |                            nan |
+----+------------------+-------------------------------------+--------------------------------+

如何将特定列中等于 Older than 100 的值替换为 nan

+----+------------------+-------------------------------------+--------------------------------+
|    |   AgeAt_X        |   AgeAt_Y                           |   AgeAt_Z                      |
|----+------------------+-------------------------------------+--------------------------------+
|  0 |              nan |                                 nan |                          74.13 |
|  1 |              nan |                                 nan |                          58.46 |
|  2 |              nan |                                 8.4 |                          54.15 |
|  3 |              nan |                                 nan |                          57.04 |
|  4 |              nan |                               57.04 |                            nan |
+----+------------------+-------------------------------------+--------------------------------+

备注

  • 从所需列中删除 Older than 100 字符串后,我将列转换为数字,以便对所述列执行计算。
  • 此数据框中的其他列(我已从本示例中排除)不会转换为数字,因此必须一次将一列转换为数字。

我的尝试

尝试 1

if df.isin('Older than 100'):
    df.loc[df['AgeAt_X']] = ''
else:
    df['AgeAt_X'] = pd.to_numeric(df["AgeAt_X"])

尝试 2

if df.loc[df['AgeAt_X']] == 'Older than 100r':
    df.loc[df['AgeAt_X']] = ''
elif df.loc[df['AgeAt_X']] == '':
    df['AgeAt_X'] = pd.to_numeric(df["AgeAt_X"])

尝试 3

df['AgeAt_X'] = ['' if ele == 'Older than 100' else df.loc[df['AgeAt_X']] for ele in df['AgeAt_X']]

尝试 1、2 和 3 返回以下错误:

KeyError: 'None of [0 NaN\n1 NaN\n2 NaN\n3 NaN\n4 NaN\n5 NaN\n6 NaN\n7 NaN\n8 NaN\n9 NaN\n10 NaN\n11 NaN\n12 NaN\n13 NaN\n14 NaN\n15 NaN\n16 NaN\n17 NaN\n18 NaN\n19 NaN\n20 NaN\n21 NaN\n22 NaN\n23 NaN\n24 NaN\n25 NaN\n26 NaN\n27 NaN\n28 NaN\n29 NaN\n ..\n6332 NaN\n6333 NaN\n6334 NaN\n6335 NaN\n6336 NaN\n6337 NaN\n6338 NaN\n6339 NaN\n6340 NaN\n6341 NaN\n6342 NaN\n6343 NaN\n6344 NaN\n6345 NaN\n6346 NaN\n6347 NaN\n6348 NaN\n6349 NaN\n6350 NaN\n6351 NaN\n6352 NaN\n6353 NaN\n6354 NaN\n6355 NaN\n6356 NaN\n6357 NaN\n6358 NaN\n6359 NaN\n6360 NaN\n6361 NaN\nName: AgeAt_X, Length: 6362, dtype: float64] are in the [index]'

尝试 4

df['AgeAt_X'] = df['AgeAt_X'].replace({'Older than 100': ''})

尝试 4 返回以下错误:

TypeError: Cannot compare types 'ndarray(dtype=float64)' and 'str'

我也看过一些帖子。下面两个实际上并没有替换值,而是创建了一个从其他人派生的新列

Replace specific values in Pandas DataFrame

Pandas replace DataFrame values

【问题讨论】:

  • 您是否有任何理由希望在列中保留其他非数字值?如果没有,而事实证明 'Older than 100' 是唯一有问题的字符串,那么要走的路是 pd.to_numeric(df['col_name'], errors='coerce')
  • @ALollz,好主意。我会试试这个,明天再报告。谢谢!
  • @ALollz,我相信您的解决方案是迄今为止最好的。来自文档If ‘coerce’, then invalid parsing will be set as NaN (pandas.pydata.org/pandas-docs/stable/reference/api/…)。这正是我需要的,只需要设置一个参数,不需要额外的代码。谢谢!

标签: python-3.x pandas replace


【解决方案1】:

如果我对您的理解正确,您可以将所有出现的Older than 100 替换为np.nan,只需调用DataFrame.replace。如果所有剩余的值都是数字,那么替换将隐式地将列的数据类型更改为数字

# Minimal example DataFrame
df = pd.DataFrame({'AgeAt_X': ['Older than 100', np.nan, np.nan],
                   'AgeAt_Y': ['Older than 100', np.nan, 8.4],
                   'AgeAt_Z': [74.13, 58.46, 54.15]})
df
          AgeAt_X         AgeAt_Y  AgeAt_Z
0  Older than 100  Older than 100    74.13
1             NaN             NaN    58.46
2             NaN             8.4    54.15

df.dtypes
AgeAt_X     object
AgeAt_Y     object
AgeAt_Z    float64
dtype: object

# Replace occurrences of 'Older than 100' with np.nan in any column
df.replace('Older than 100', np.nan, inplace=True)

df
   AgeAt_X  AgeAt_Y  AgeAt_Z
0      NaN      NaN    74.13
1      NaN      NaN    58.46
2      NaN      8.4    54.15

df.dtypes
AgeAt_X    float64
AgeAt_Y    float64
AgeAt_Z    float64
dtype: object

【讨论】:

  • 这适用于他的示例,但在转换为数字时这还不够,因为它不会检查每列中是否存在Older than 100
  • 感谢@Peter Leimbigler,您的解决方案确实有效,但 Erfan 的解决方案也有效,但也减轻了我识别要转换为数字的列的需要,因为如果它们包含 Older than 100,我无论如何都要转换它们。
  • 其实没有必要显式转换为数值数据类型。如果字符串替换导致一列包含所有数值,pandas 会将该列的数据类型隐式转换为数值类型,在本例中为 float64。我已经编辑了我的答案以反映这种行为。
  • 虽然,对于一个包含类似数字的值和字符串的对象列,pandas 通常会在1 中读取为'1',并且在这些情况下它不会进行类型转换(数据喜欢7,8;foo,9)
  • @Alollz,好点子,这个示例数据看起来不是这种情况,但可能会出现在其他列中。
【解决方案2】:

我们可以遍历每一列并检查句子是否存在。如果命中,我们用Series.str.replace 将句子替换为NaN,并在将其转换为数字后立即使用Series.astype,在本例中为float

df.dtypes
AgeAt_X     object
AgeAt_Y     object
AgeAt_Z    float64
dtype: object

sent = 'Older than 100'

for col in df.columns:
    if sent in df[col].values:
        df[col] = df[col].str.replace(sent, 'NaN')
        df[col] = df[col].astype(float)

print(df)
   AgeAt_X  AgeAt_Y  AgeAt_Z
0      NaN      NaN    74.13
1      NaN      NaN    58.46
2      NaN     8.40    54.15
3      NaN      NaN    57.04
4      NaN    57.04      NaN

df.dtypes
AgeAt_X    float64
AgeAt_Y    float64
AgeAt_Z    float64
dtype: object

【讨论】:

  • 感谢@Erfan,这个解决方案为我节省了识别要单独转换为数字的列的步骤。
  • 不错的解决方案,但 for 循环和 .astype(float) 行是不必要的,因为如果替换导致列包含所有数值,pandas 会自动将该列转换为数字数据类型。更短的解决方案是df.replace('Older than 100', np.nan, inplace=True)
猜你喜欢
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 2019-10-12
  • 2022-06-24
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2021-12-04
相关资源
最近更新 更多