Python中无聚合合并同日期同Item且含None值的DataFrame行
问题
我有如下Python DataFrame:
Date | Item | B1 | B1 Quantity | B2 | B2 Quantity 2-18-2019 | NY01 | dNo | efa | None | None 2-18-2019 | NY01 | 1dfs | e3f3 | None | None 2-18-2019 | NY01 | None | None | 85 | q2d 2-19-2019 | Du02 | dfgwe | eef | None | None 2-19-2019 | Du01 | None | None | ddd | fve3 2-20-2019 | Ps55 | df | fdr | None | None 2-20-2019 | Ps55 | None | None | 6edc | ewc 2-20-2019 | Du85 | hiid | 41fe18 | None | None 2-20-2019 | Du85 | fvcv | fe3v | None | None 2-20-2019 | Du85 | None | None | Neww | Newe 2-20-2019 | Du85 | None | None | dfi | dc
要求:当Date和Item值相同时,将同组内后续行的非None值填充到对应行的None位置;完成填充后删除仅包含B2相关列的行,最终得到如下结果:
Date | Item | B1 | B1 Quantity | B2 | B2 Quantity 2-18-2019 | NY01 | dNo | efa | None | None 2-18-2019 | NY01 | 1dfs | e3f3 | 85 | q2d 2-19-2019 | Du02 | dfgwe | eef | ddd | fve3 2-20-2019 | Ps55 | df | fdr | 6edc | ewc 2-20-2019 | Du85 | hiid | 41fe18 | Neww | Newe 2-20-2019 | Du85 | fvcv | fe3v | dfi | dc
解决方案
核心思路
- 按
Date和Item分组(若需按日期统一处理所有Item,可修改分组键) - 每个分组内分离出包含
B1数据的行和包含B2数据的行 - 将
B2数据按索引对应填充到B1行中,多余的B2行可按需补充 - 合并所有分组的处理结果
代码实现
import pandas as pd # 构建原始DataFrame data = { 'Date': ['2-18-2019', '2-18-2019', '2-18-2019', '2-19-2019', '2-19-2019', '2-20-2019', '2-20-2019', '2-20-2019', '2-20-2019', '2-20-2019', '2-20-2019'], 'Item': ['NY01', 'NY01', 'NY01', 'Du02', 'Du01', 'Ps55', 'Ps55', 'Du85', 'Du85', 'Du85', 'Du85'], 'B1': ['dNo', '1dfs', None, 'dfgwe', None, 'df', None, 'hiid', 'fvcv', None, None], 'B1 Quantity': ['efa', 'e3f3', None, 'eef', None, 'fdr', None, '41fe18', 'fe3v', None, None], 'B2': [None, None, '85', None, 'ddd', None, '6edc', None, None, 'Neww', 'dfi'], 'B2 Quantity': [None, None, 'q2d', None, 'fve3', None, 'ewc', None, None, 'Newe', 'dc'] } df = pd.DataFrame(data) def process_group(group): # 提取包含B1数据的行(排除B1和B1 Quantity全为空的行) df_b1 = group.dropna(subset=['B1', 'B1 Quantity'], how='all').reset_index(drop=True) # 提取包含B2数据的行(排除B2和B2 Quantity全为空的行) df_b2 = group.dropna(subset=['B2', 'B2 Quantity'], how='all').reset_index(drop=True) # 将B2数据按索引对应填充到B1行中 merged = df_b1.join(df_b2[['B2', 'B2 Quantity']], how='left') # 若B2行数量多于B1行,将多余的B2行转为B1为空的行补充进去(可选) if len(df_b2) > len(df_b1): extra_b2 = df_b2.iloc[len(df_b1):].copy() extra_b2[['B1', 'B1 Quantity']] = None merged = pd.concat([merged, extra_b2], ignore_index=True) return merged # 按Date+Item分组处理,若需按日期统一处理,将分组键改为['Date'] result = df.groupby(['Date', 'Item'], group_keys=False).apply(process_group) # 重置索引 result = result.reset_index(drop=True) print(result)
说明
- 若要实现示例中2-19-2019行合并Du02和Du01数据的效果,只需将分组键改为
['Date'],即可按日期统一处理所有Item的数据 - 代码中
dropna的how='all'确保仅排除对应列全为空的行,避免误删部分有值的行
内容的提问来源于stack exchange,提问作者SMO
相关产品推荐
相关产品推荐

