在 pandas 中使用 lambda 函数过滤掉空值

Filtering out null values with a lambda function in pandas

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

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 将参数作为 float 对象传递而不只是常规 float 的事实有关。

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

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) 适用于我的示例数据,但不适用于我的生产数据集,因此它一定只是我数据中某处的一个奇怪的怪癖。对于上下文,我的生产数据集中的 phone 数字必须是 NaN、以 1 开头的 11 位数字字符串或 10 位数字字符串。但是,当我在我的生产数据集上 运行 我的 lambda 函数时,我收到错误“'float' 类型的对象没有 len()”,所以不知何故一些 floats/NaNs 正在滑过我的 if 语句

来自这个虚构的 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

这是一段有效的代码,您必须使用 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