【问题标题】:Handling NaN Values in Pandas with Conditional Statement使用条件语句处理 Pandas 中的 NaN 值
【发布时间】:2019-01-30 00:03:43
【问题描述】:

我正在处理一些客户邮政编码数据无效的数据。结果,我无法将 CountryISOCode 映射到他们的邮政编码,从而导致 NaN。但是,我注意到对于所有带有 NaN 的 CountryISOCodes,CurrencyCode 可以为我提供足够的信息来暂时解决问题。

我已经阅读了各种 Stackoverflow 文章,但找不到解决问题的方法。我试过了……

def func(row):
    if row['CountryISOCode'] == np.nan & row['Currency'] == 'EUR':
        return 'IRE'
elif row['CountryISOCode'] == np.nan & row['Currency'] == 'GBP':
    return 'GBR'
else:
    return row['CountryISOCode']

df['CountryISOCode'] = df.apply(func, axis=1)

还有其他一些方法,但无济于事......

下面我提供了我正在使用的数据的复制

import pandas as pd
import numpy as np

data = [
    ['Steve', 'Invalid Postcode', 'GBP', np.nan ],
    ['Robyn', 'Invalid Postcode', 'EUR', np.nan],
    ['James', 'Valid Postcode', 'GBP', 'GBR'],
    ['Halo', 'Invalid Postcode', 'EUR', np.nan],
    ['Jesus', 'Valid Postcode', 'GBP', 'GBR']
    ]

df = pd.DataFrame(columns=["Name", "PostCode", "CurrencyCode", "CountryISOCode"], data=data)

基本上,如果我使用 SQL,我的代码将如下所示。

IF countryISOCode IS NULL 
    AND currency = ‘GBP’ 
THEN CountryISOCode =  ‘GBR’
ELSE
IF countryISOCode IS NULL 
    AND currency = ‘EUR 
THEN CountryISOCode =  ‘IRE’
ELSE countryISOCode 
END

有什么想法吗?

【问题讨论】:

  • 您是否尝试将& 更改为and?两者有区别,我想你想在这里使用and。您可以在此处查看更多关于差异的信息 [stackoverflow.com/questions/22646463/…
  • 代码使用and 运行,但似乎无法解决问题。数据保持不变。

标签: python pandas


【解决方案1】:

您可以将fillna 与字典一起使用,以指定货币代码何时有用的映射:

cmap = {'GBP': 'GBR', 'EUR': 'IRE'}
df['CountryISOCode'] = df['CountryISOCode'].fillna(df['CurrencyCode'].map(cmap))

print(df)

    Name          PostCode CurrencyCode CountryISOCode
0  Steve  Invalid Postcode          GBP            GBR
1  Robyn  Invalid Postcode          EUR            IRE
2  James    Valid Postcode          GBP            GBR
3   Halo  Invalid Postcode          EUR            IRE
4  Jesus    Valid Postcode          GBP            GBR

【讨论】:

  • 这个解决方案以最简单的方式解决了我的问题......一个小的变化是它应该是cmap = {'GBP': 'GBR', 'EUR': 'IRE'}
【解决方案2】:

您可以为此使用np.select,它允许您根据条件列表的结果从列表中进行选择:

m1 = df.CountryISOCode.isna()
m2 = df.CurrencyCode.eq('GBP')
m3 = df.CurrencyCode.eq('EUR')
df.loc[:,'CountryISOCode'] = np.select([m1&m2, m1&m3], ['GBP','IRE'], 
                                       default=df.CountryISOCode)

 Name          PostCode CurrencyCode CountryISOCode
0  Steve  Invalid Postcode          GBP            GBP
1  Robyn  Invalid Postcode          EUR            IRE
2  James    Valid Postcode          GBP            GBR
3   Halo  Invalid Postcode          EUR            IRE
4  Jesus    Valid Postcode          GBP            GBR

【讨论】:

  • 这种方法有效,但是用 IRE 填充 GBP 值是行不通的。索引 2
  • 感谢您回答我的问题!你的解决方案奏效了。
【解决方案3】:

我添加此答案是因为它为原始问题增加了价值。比较语句不起作用的原因是 np.nan == np.nan 不起作用。您可以检查 NaN 元素的身份,但不能检查相等性。有关更多详细信息,请参阅in operator, float("NaN") and np.nan。话虽如此,这就是您可以转换原始代码以使其按预期工作的方法。

import pandas as pd                                                                                                                                    
import numpy as np

raw_data = [
    ['Steve', 'Invalid Postcode', 'GBP', np.nan ],
    ['Robyn', 'Invalid Postcode', 'EUR', np.nan],
    ['James', 'Valid Postcode', 'GBP', 'GBR'],
    ['Halo', 'Invalid Postcode', 'EUR', np.nan],
    ['Jesus', 'Valid Postcode', 'GBP', 'GBR']
    ]

df = pd.DataFrame(columns=["Name", "PostCode", "Currency", "CountryISOCode"], data=raw_data)

def func(row):
    if row['CountryISOCode'] is np.nan and row['Currency'] == 'EUR':
        return 'IRE'
    elif row['CountryISOCode'] is np.nan and row['Currency'] == 'GBP':
        return 'GBR'
    else:
        return row['CountryISOCode']

df['CountryISOCode'] = df.apply(func, axis=1)

print(df)

不过,其他答案也很棒。

【讨论】:

    【解决方案4】:

    对多个条件和多个选择使用np.select()

    df['CountryISOCode']=np.select([(df.CurrencyCode=='GBP')&(df.CountryISOCode.isna()),\
                                (df.CurrencyCode=='EUR')&df.CountryISOCode.isna()],['GBR','IRE'],\
                               default=df.CountryISOCode)
    
        Name          PostCode CurrencyCode CountryISOCode
    0  Steve  Invalid Postcode          GBP            GBR
    1  Robyn  Invalid Postcode          EUR            IRE
    2  James    Valid Postcode          GBP            GBR
    3   Halo  Invalid Postcode          EUR            IRE
    4  Jesus    Valid Postcode          GBP            GBR
    

    【讨论】:

    • 感谢您回答我的问题!你的解决方案奏效了。
    【解决方案5】:

    虽然使用np.select 的其他答案有效,但我个人最喜欢使用mask

    df['CountryISOCode'] = df['CountryISOCode'] \
        .mask(df['CountryISOCode'].isna() & df['Currency'].eq('GBP'), 'GBR') \
        .mask(df['CountryISOCode'].isna() & df['Currency'].eq('EUR'), 'IRE')
    

    【讨论】:

    • 感谢您回答我的问题!
    猜你喜欢
    • 2023-03-10
    • 2017-05-27
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 2016-06-06
    • 1970-01-01
    • 2020-11-27
    • 2018-01-01
    相关资源
    最近更新 更多