如何基于多列条件在Pandas DataFrame中创建新列?
问题描述
我有一个包含A、B、C、D、E列的Pandas DataFrame,各列的值仅为0或1,数据如下:
| A | B | C | D | E |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 | 0 |
| 0 | 0 | 0 | 0 | 1 |
需求是创建新列“F”:当A、B、C、D、E任意一列包含1时,F的值为1;否则为0。预期输出如下:
| A | B | C | D | E | F |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 1 | 0 | 1 |
| 0 | 0 | 0 | 0 | 1 | 1 |
我尝试了以下代码:
def stress(df1): if 0 not in ('A', 'B', 'C', 'D', 'E'): return 1 else: return 0 df1['F'] = df1.apply(stress, axis=1) df1
但得到的结果不符合预期,所有F列的值均为1:
| A | B | C | D | E | F |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 | 1 |
| 0 | 1 | 0 | 0 | 0 | 1 |
| 0 | 0 | 1 | 1 | 0 | 1 |
| 0 | 0 | 0 | 0 | 1 | 1 |
同时出现警告:
c:\python39\lib\site-packages\pandas\core\frame.py:3607: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy self._set_item(key, value)
请提供正确的实现方法并解决警告问题。
解决方案
错误原因
- 逻辑错误:自定义函数里判断的是
0 not in ('A', 'B', 'C', 'D', 'E'),这是在检查字符串"0"是否在列名列表里,结果永远为真,所以所有行返回1。正确逻辑应该是检查当前行的A-E列数值中是否存在1。 - 警告原因:
df1大概率是其他DataFrame的切片副本,直接修改副本会触发Pandas的修改警告。
正确实现方法
方法一:向量化操作(推荐,效率更高)
利用Pandas的any()方法直接对每行进行判断,再转成整数类型:
# 先创建独立副本,解决警告问题 df1 = df1.copy() # 生成F列:每行A-E列只要有一个1,F就是1,否则为0 df1['F'] = df1[['A', 'B', 'C', 'D', 'E']].any(axis=1).astype(int)
方法二:修正自定义函数
如果一定要用apply,需修改函数逻辑以正确获取行数据:
df1 = df1.copy() def stress(row): # 检查当前行的A-E列数值中是否存在1 return 1 if 1 in row[['A', 'B', 'C', 'D', 'E']].values else 0 df1['F'] = df1.apply(stress, axis=1)
警告解决
出现SettingWithCopyWarning的核心是df1是其他DataFrame的切片副本,解决方式:
- 在修改
df1前执行df1 = df1.copy(),创建一个独立的DataFrame副本,后续操作就不会触发警告。
内容的提问来源于stack exchange,提问作者Nasi Padang
相关产品推荐
相关产品推荐

