在 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
我有一个数据框,其中一行为 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