使用Pandas实现同邮箱行空值填充:复制下一行对应值
问题解决:按邮箱分组填充首行空值
错误原因
你写的df['NAME'][i]取的是单个元素(空值对应float类型的NaN),而fillna()是Pandas Series/DataFrame的方法,单个元素无法调用该方法,因此抛出AttributeError: 'float' object has no attribute 'fillna'。
正确实现方法
方法一:分组处理(直观易读)
按邮箱分组后,检查每组首行的目标列是否为空,若为空则用组内第二行的值填充:
import pandas as pd # 模拟你的输入DataFrame df = pd.DataFrame({ 'EMAIL': ['a@a.com', 'a@a.com', 'b@b.com', 'c@c.com', 'c@c.com'], 'NAME': [None, 'AAA', 'BBB', None, 'CCC'], 'AGE': [None, 25, 30, None, 35] }) def fill_group_first_row(group): # 遍历需要填充的列(可根据需求添加更多列) for col in ['NAME', 'AGE']: # 仅当组内至少有两行,且首行该列为空时填充 if len(group) >= 2 and pd.isna(group[col].iloc[0]): group[col].iloc[0] = group[col].iloc[1] return group # 分组应用处理逻辑 df_filled = df.groupby('EMAIL', group_keys=False).apply(fill_group_first_row) print(df_filled)
输出结果:
EMAIL NAME AGE 0 a@a.com AAA 25.0 1 a@a.com AAA 25.0 2 b@b.com BBB 30.0 3 c@c.com CCC 35.0 4 c@c.com CCC 35.0
方法二:向量化操作(高效适合大数据)
用cumcount()标记组内首行,结合shift(-1)取下行值填充,无需逐组循环:
import pandas as pd df = pd.DataFrame({ 'EMAIL': ['a@a.com', 'a@a.com', 'b@b.com', 'c@c.com', 'c@c.com'], 'NAME': [None, 'AAA', 'BBB', None, 'CCC'], 'AGE': [None, 25, 30, None, 35] }) # 对每个需要填充的列执行逻辑 for col in ['NAME', 'AGE']: # 筛选条件:组内首行 且 该列值为空 fill_mask = (df.groupby('EMAIL')[col].cumcount() == 0) & df[col].isna() # 用下一行的值填充符合条件的行 df.loc[fill_mask, col] = df.loc[fill_mask, col].shift(-1) print(df)
注意事项
- 如果同一邮箱组内首行空,但下一行也为空,填充后仍为空;若需要取组内第一个非空值,可修改逻辑为
group[col].iloc[0] = group[col].dropna().iloc[0] - 尽量避免逐行遍历DataFrame,Pandas的向量化/分组操作效率远高于循环
内容的提问来源于stack exchange,提问作者vigneshwaran sr
相关产品推荐
相关产品推荐

