【问题标题】:Filtering out null values with a lambda function in pandas在 pandas 中使用 lambda 函数过滤掉空值
【发布时间】:2022-01-20 18:15:11
【问题描述】:

我有一个数据框,其中有一排电话号码。我编写了以下函数来用空字符串填充任何 NaN,然后​​将“+”和“1”添加到任何需要它们的电话号码。

def fixCampaignerPhone(phone):
    if phone.isnull():
        phone = ''
    phone = str(phone)
    if len(phone) == 10:
        phone = ('1' + phone)
    if len(phone) > 1:
        phone = ('+' + phone)
    return phone

我尝试将此函数应用于数据框的列,如下所示: df['phone'] = df.apply(lambda row: fixCampaignerPhone(row['phone']), axis =1)

我的函数没有正确识别和替换 NaN 值。错误“'float' 类型的对象没有 len()”我在单独的行上使用 .fillna() 解决了它,但我想了解 为什么 这不起作用。如果我手动传递一个 NaN 值,该函数就可以工作,所以我认为这与 pandas 将参数作为浮点对象传递,而不仅仅是常规浮点数有关。

编辑:带有用于调试的示例数据的完整工作代码。

import pandas as pd
import numpy as np

def fixCampaignerPhone(phone):# adds + and 1 to front of phone numbers if necessary
    if phone.isnull():
        phone = ''
    phone = str(phone)
    if len(phone) == 10:
        phone = ('1' + phone)
    if len(phone) > 1:
        phone = ('+' + phone)
    return phone

d = {0: float("NaN"), 1:"2025676789"}
sampledata = pd.Series(data = d, index = [0 , 1])
sampledata.apply(lambda row: fixCampaignerPhone(row))

编辑 2: 将 phone.isnull() 更改为 pd.isna(phone) 适用于我的示例数据,但不适用于我的生产数据集,所以它一定只是我数据中某个地方的一个奇怪的怪癖。对于上下文,我的生产数据集中的电话号码必须是 NaN、以 1 开头的 11 位字符串或 10 位字符串。但是,当我在生产数据集上运行我的 lambda 函数时,我收到错误“'float' 类型的对象没有 len()”,所以不知何故,一些浮点数/NaN 正在滑过我的 if 语句

【问题讨论】:

  • 请提供完整的工作代码示例,以便我们重现并帮助您调试。
  • @Malo 已添加,谢谢
  • 您必须决定电话变量的类型。它是一个带有电话号码的字符串吗?还是浮点格式?那么“isnull”既不是字符串也不是浮点函数。你必须改变它。
  • @Malo 更新了我的帖子,但我确实意识到“isnull”的问题数据是生产数据,并且系列是浮点对象 nan 或字符串。不幸的是,我无法强制执行单一数据类型
  • 请看看我的回答,我成功了。你必须写 pd.isnull(phone)

标签: python pandas lambda null


【解决方案1】:

来自这个虚构的 DataFrame:

>>> import pandas as pd
>>> from io import StringIO

>>> df = pd.read_csv(StringIO("""
A,phone
L,3453454564
L,345345
R,345345
h,3
A,345345
L,345345
R,3453434543
R,345345
R,345345
R,345345
"""), sep=',')
>>> df
    A   phone
0   L   3453454564
1   L   345345
2   R   345345
3   h   3
4   A   345345
5   L   345345
6   R   3453434543
7   R   345345
8   R   345345
9   R   345345

我们可以使用numpy 中的select 来构建我们的if 段并获得预期的结果:

import numpy as np

df['phone'] = df['phone'].astype(str)

condlist = [df['phone'].str.len() == 10, 
            df['phone'].str.len() > 1]

choicelist = ['1' + df['phone'],
              '+' + df['phone']]            

df['phone'] = np.select(condlist, choicelist, default='')

输出:

    A   phone
0   L   13453454564
1   L   +345345
2   R   +345345
3   h   
4   A   +345345
5   L   +345345
6   R   13453434543
7   R   +345345
8   R   +345345
9   R   +345345

【讨论】:

    【解决方案2】:

    这是一段工作代码,你必须使用 pd.isnull(phone) 而不是 phone.isnull():

    import pandas as pd
    import numpy as np
    
    def fixCampaignerPhone(phone):# adds + and 1 to front of phone numbers if necessary
        if pd.isnull(phone):
            phone = ''
        phone = str(phone)
        if len(phone) == 10:
            phone = ('1' + phone)
        if len(phone) > 1:
            phone = ('+' + phone)
        return phone
    
    d = {0: float("NaN"), 1:"2025676789"}
    sampledata = pd.Series(data = d, index = [0 , 1])
    r=sampledata.apply(lambda row: fixCampaignerPhone(row))
    
    print(r)
    

    结果是:

    0                
    1    +12025676789
    dtype: object
    

    【讨论】:

    • 由于我的问题几乎可以肯定是我的数据集,并且这适用于样本,我将继续接受这个,谢谢
    • 你还有一些不合格的样品吗?
    猜你喜欢
    • 2017-08-15
    • 2019-03-17
    • 1970-01-01
    • 2017-08-24
    • 2018-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    相关资源
    最近更新 更多