如何在Pandas DataFrame中对列的子集执行计算并修改原数据
问题场景
现有如下数据集(通过pd.wide_to_long生成):
famid birth age ht 0 1 1 one 2.8 1 1 1 two 3.4 2 1 2 one 2.9 3 1 2 two 3.8 4 1 3 one 2.2 5 1 3 two 2.9
需要仅修改df['ht']中满足df['age'] == 'one'的子集数据,且不新建列。尝试以下代码后数据未变化,还触发**"A value is trying to be set on a copy of a slice from a DataFrame"**警告:
df[df['age']=='one']['ht'] = df[df['age']=='one']['ht']*10**6
尝试过df.mask()和df.where()方法也未生效,求正确实现方式。
可复现数据集代码:
import pandas as pd df = pd.DataFrame({ 'famid': [1, 1, 1, 2, 2, 2, 3, 3, 3], 'birth': [1, 2, 3, 1, 2, 3, 1, 2, 3], 'ht_one': [2.8, 2.9, 2.2, 2, 1.8, 1.9, 2.2, 2.3, 2.1], 'ht_two': [3.4, 3.8, 2.9, 3.2, 2.8, 2.4, 3.3, 3.4, 2.9] }) df = pd.wide_to_long(df, stubnames='ht', i=['famid', 'birth'], j='age', sep='_', suffix=r'\w+') df.reset_index(inplace = True)
问题根源
原代码用了链式索引df[df['age']=='one']['ht'],这种写法会返回原DataFrame的副本而非视图,对副本赋值不会影响原DataFrame,这就是数据没变化且触发警告的原因。
正确实现方法
方法1:使用.loc定位赋值(推荐)
通过.loc直接定位到目标行和列,直接修改原DataFrame:
df.loc[df['age'] == 'one', 'ht'] *= 10**6
也可以写成展开形式:
df.loc[df['age'] == 'one', 'ht'] = df.loc[df['age'] == 'one', 'ht'] * 10**6
.loc是Pandas官方推荐的修改数据方式,能确保操作的是原DataFrame的视图,避免副本问题。
方法2:使用np.where替换
借助numpy.where根据条件生成新值,直接替换原列:
import numpy as np df['ht'] = np.where(df['age'] == 'one', df['ht']*10**6, df['ht'])
方法3:正确使用mask/where
之前用这两个方法没生效是因为未正确赋值,正确写法如下:
mask:当条件为True时替换对应值
df['ht'] = df['ht'].mask(df['age'] == 'one', df['ht']*10**6)
where:当条件为False时替换对应值,因此需要取反判断条件
df['ht'] = df['ht'].where(df['age'] != 'one', df['ht']*10**6)
内容的提问来源于stack exchange,提问作者vestland
相关产品推荐
相关产品推荐

