如何在Pandas DataFrame中按指定Type列值(含空值)拼接字段
解决Pandas中根据Type字段拼接Name与City/Email的空值处理问题
我有一个带Type字段的Pandas DataFrame,包含Name、City、Email信息。需要根据Type的值,将Name分别和City或Email拼接成新列concat_name,但Type列存在空值,处理时出现歧义错误,空值的正确识别是当前难点。
数据与期望结果
NULL = None data = { 'Type': [NULL, 'MasterCard', 'Visa','Amex'], 'Name': ['Chris','John','Jill','Mary'], 'City': ['Tustin','Cleveland',NULL,NULL ], 'Email': [NULL,NULL,'jdoe@yahoo.com','mdoe@aol.com'] } df_data = pd.DataFrame(data)
期望生成的concat_name列:
df_data['concat_name'] = ['ChrisTustin', 'JohnCleveland','Jilljdoe@yahoo.com','Marymdoe@aol.com']
尝试方案及报错
尝试一:布尔判断
if df_data['Type'].isnull() | df_data[df_data['Type'] == 'Mastercard': df_data['concat_name'] = df_data['Name']+df_data['City'] if df_data[df_data['Type'] == 'Visa' | df_data[df_data['Type'] == 'Amex': df_data['concat_name'] = df_data['Name']+df_data['Email'] else: df_data['concat_name'] = 'Error'
报错:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
尝试二:np.where
df_data['concat_name'] = np.where((df_data['Type'].isna()|(df_data['Type']=='MasterCard'),df_data['Name']+df_data['City'], np.where((df_data['Type']=="Visa")|(df_data['Type']=="Amex"),df_data['Name']+df_data['Email'], 'Error'
报错:
ValueError: Length of values(2) does not match length of index(12000)
错误原因分析
尝试一问题:
- 直接用
if判断返回Series的表达式(如df_data['Type'].isnull()),Python无法确定整个Series的真值(包含多个布尔值),因此抛出歧义错误。 - 存在语法错误:括号不匹配、
Mastercard大小写与原数据的MasterCard不匹配。 - 连续
if会覆盖之前的赋值,逻辑逻辑存在漏洞。
- 直接用
尝试二问题:
- 括号不匹配导致
np.where参数传递错误,返回结果长度与索引不匹配。 - 未处理City/Email可能存在的空值,实际场景中可能生成NaN。
- 括号不匹配导致
正确解决方案
方案一:修正后的np.where写法
import numpy as np import pandas as pd NULL = None data = { 'Type': [NULL, 'MasterCard', 'Visa','Amex'], 'Name': ['Chris','John','Jill','Mary'], 'City': ['Tustin','Cleveland',NULL,NULL ], 'Email': [NULL,NULL,'jdoe@yahoo.com','mdoe@aol.com'] } df_data = pd.DataFrame(data) df_data['concat_name'] = np.where( df_data['Type'].isna() | (df_data['Type'] == 'MasterCard'), df_data['Name'] + df_data['City'].fillna(''), np.where( (df_data['Type'] == 'Visa') | (df_data['Type'] == 'Amex'), df_data['Name'] + df_data['Email'].fillna(''), 'Error' ) )
方案二:使用df.loc条件赋值(更直观)
import pandas as pd NULL = None data = { 'Type': [NULL, 'MasterCard', 'Visa','Amex'], 'Name': ['Chris','John','Jill','Mary'], 'City': ['Tustin','Cleveland',NULL,NULL ], 'Email': [NULL,NULL,'jdoe@yahoo.com','mdoe@aol.com'] } df_data = pd.DataFrame(data) # 初始化默认值 df_data['concat_name'] = 'Error' # Type为空或MasterCard时,拼接Name和City mask1 = df_data['Type'].isna() | (df_data['Type'] == 'MasterCard') df_data.loc[mask1, 'concat_name'] = df_data.loc[mask1, 'Name'] + df_data.loc[mask1, 'City'] # Type为Visa或Amex时,拼接Name和Email mask2 = (df_data['Type'] == 'Visa') | (df_data['Type'] == 'Amex') df_data.loc[mask2, 'concat_name'] = df_data.loc[mask2, 'Name'] + df_data.loc[mask2, 'Email']
两种方案都能得到期望的concat_name列,且处理了空值场景的潜在问题。
内容的提问来源于stack exchange,提问作者hSin
相关产品推荐
相关产品推荐

