
在数据分析和处理中,我们经常需要根据复杂的业务逻辑来生成新的数据列。一个常见的需求是,在对数据进行分组后,根据组内是否存在特定条件,来决定新列的填充方式。
考虑以下原始DataFrame:
| index | Col1 | Col2 | Col3 |
|---|---|---|---|
| 0 | 1 | X | ABC |
| 1 | 1 | Y | XX |
| 2 | 1 | X | QW |
| 3 | 2 | X | VB |
| 4 | 2 | X | AY |
| 5 | 3 | X | MM |
| 6 | 3 | X | YY |
| 7 | 3 | Y | XX |
我们的目标是创建一个名为 New_Col 的新列,其填充逻辑如下:
根据上述规则,期望的输出DataFrame应为:
| Col1 | Col2 | Col3 | New_Col |
|---|---|---|---|
| 1 | X | ABC | XX |
| 1 | Y | XX | XX |
| 1 | X | QW | XX |
| 2 | X | VB | VB |
| 2 | X | AY | AY |
| 3 | X | MM | XX |
| 3 | X | YY | XX |
| 3 | Y | XX | XX |
为了高效地实现这一复杂的条件填充逻辑,我们可以利用Pandas的链式操作,结合 mask、groupby().transform('first') 和 fillna 方法。这种方法避免了显式的循环,充分利用了Pandas的向量化操作,从而提高了处理效率。
核心思路是:
让我们通过代码示例逐步分解这个解决方案。
首先,初始化我们的DataFrame:
import pandas as pd
import numpy as np
data = {
'Col1': [1, 1, 1, 2, 2, 3, 3, 3],
'Col2': ['X', 'Y', 'X', 'X', 'X', 'X', 'X', 'Y'],
'Col3': ['ABC', 'XX', 'QW', 'VB', 'AY', 'MM', 'YY', 'XX']
}
df = pd.DataFrame(data)
print("原始 DataFrame:")
print(df)输出:
原始 DataFrame: Col1 Col2 Col3 0 1 X ABC 1 1 Y XX 2 1 X QW 3 2 X VB 4 2 X AY 5 3 X MM 6 3 X YY 7 3 Y XX
我们首先要找出那些 Col2 列为 'Y' 的行,并获取其对应的 Col3 值。对于 Col2 不为 'Y' 的行,我们将其 Col3 值替换为 NaN。这可以通过 mask 方法实现。mask(condition, other) 会在 condition 为 True 的地方保留原始值,在 condition 为 False 的地方替换为 other。这里我们希望在 Col2 != 'Y' 的地方替换为 NaN。
# 步骤一:根据Col2 != 'Y' 条件掩盖Col3的值
masked_col3 = df['Col3'].mask(df['Col2'] != 'Y')
print("\n步骤一:掩盖后的 Col3 (masked_col3):")
print(masked_col3)输出:
步骤一:掩盖后的 Col3 (masked_col3): 0 NaN 1 XX 2 NaN 3 NaN 4 NaN 5 NaN 6 NaN 7 XX Name: Col3, dtype: object
可以看到,只有 Col2 为 'Y' 的行(索引1和7)保留了其 Col3 值,其他行都被替换成了 NaN。
接下来,我们需要对 masked_col3 进行分组操作。对于每个 Col1 组,我们希望找到其中第一个非 NaN 的值,并将其广播到该组的所有行。groupby().transform('first') 正好能实现这一点。transform('first') 会在每个组内找到第一个非 NaN 的值,并将其填充到该组的所有位置。如果一个组内所有值都是 NaN,则 transform('first') 也会返回 NaN。
# 步骤二:按Col1分组,并获取每个组的第一个非NaN值
grouped_transformed = masked_col3.groupby(df['Col1']).transform('first')
print("\n步骤二:分组转换后的结果 (grouped_transformed):")
print(grouped_transformed)输出:
步骤二:分组转换后的结果 (grouped_transformed): 0 XX 1 XX 2 XX 3 None 4 None 5 XX 6 XX 7 XX Name: Col3, dtype: object
观察结果:
最后一步是处理那些在步骤二中仍然是 NaN(或 None)的行。这些行对应着那些 Col1 组内没有 Col2 为 'Y' 的情况。根据需求,此时应将这些 NaN 值填充回原始的 Col3 值。
# 步骤三:用原始的Col3值填充剩余的NaN
final_new_col = grouped_transformed.fillna(df['Col3'])
print("\n步骤三:最终的新列 (final_new_col):")
print(final_new_col)
df['New_Col'] = final_new_col
print("\n最终 DataFrame:")
print(df)输出:
步骤三:最终的新列 (final_new_col): 0 XX 1 XX 2 XX 3 VB 4 AY 5 XX 6 XX 7 XX Name: Col3, dtype: object 最终 DataFrame: Col1 Col2 Col3 New_Col 0 1 X ABC XX 1 1 1 Y XX XX 2 1 X QW XX 3 2 X VB VB 4 2 X AY AY 5 3 X MM XX 6 3 X YY XX 7 3 Y XX XX
至此,我们成功地生成了符合要求的新列 New_Col。
将上述步骤整合到一起,形成简洁高效的解决方案:
import pandas as pd
import numpy as np
# 原始数据
data = {
'Col1': [1, 1, 1, 2, 2, 3, 3, 3],
'Col2': ['X', 'Y', 'X', 'X', 'X', 'X', 'X', 'Y'],
'Col3': ['ABC', 'XX', 'QW', 'VB', 'AY', 'MM', 'YY', 'XX']
}
df = pd.DataFrame(data)
# 生成新列的逻辑
df['New_Col'] = (df['Col3'].mask(df['Col2'] != 'Y')
.groupby(df['Col1'])
.transform('first')
.fillna(df['Col3']))
print("最终生成的 DataFrame:")
print(df)本文介绍了一种在Pandas DataFrame中根据复杂分组条件填充新列的有效方法。通过结合使用 mask 进行条件性值筛选、groupby().transform('first') 进行组内非空值广播,以及 fillna 处理默认情况,我们能够以简洁、高效且易于理解的方式实现这一需求。这种方法在处理大规模数据集时尤其有用,因为它避免了低效的行级迭代,充分发挥了Pandas的性能优势。掌握这种模式将有助于您更灵活地进行数据清洗和特征工程。
以上就是Pandas DataFrame:基于分组条件高效填充新列的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号