Pandas中对正负值分别排名时意外修改原列的问题排查
问题原因与解决办法
问题根源
问题出在这行代码:pc = df.col.values
Pandas的Series.values返回的是原数据的numpy数组视图,并非独立副本。这意味着pc和df['col']共享同一块内存空间,你修改pc里的元素时,原DataFrame的col列会被同步改动。
修复方案
方案1:创建独立数组副本
给values加.copy(),让pc成为独立数组,修改它就不会影响原col列:
import pandas as pd import numpy as np import random data = {'col':[random.randint(-1000, 1000) for _ in range(100)]} df = pd.DataFrame(data) pos_idx = np.where(df.col > 0)[0] neg_idx = np.where(df.col < 0)[0] p = df[df.col > 0].col.values n = df[df.col < 0].col.values p_rank = np.round(p.argsort().argsort()/(len(p)-1)*100,1) n_rank = np.round((n*-1).argsort().argsort()/(len(n)-1)*100,1) # 新增.copy()创建独立副本 pc = df.col.values.copy() pc[pc > 0] = p_rank pc[pc < 0] = n_rank df['ranking'] = pc
方案2:用Pandas原生方法更优雅实现
直接用rank方法结合条件判断,避免手动操作numpy数组,更符合Pandas风格,还能保护原数据:
import pandas as pd import numpy as np import random data = {'col':[random.randint(-1000, 1000) for _ in range(100)]} df = pd.DataFrame(data) # 正数按升序排名归一化,负数按降序排名归一化,0设为NaN df['ranking'] = df.apply( lambda x: np.round(df[df['col']>0]['col'].rank(pct=True).loc[x.name]*100, 1) if x['col']>0 else (np.round(df[df['col']<0]['col'].rank(ascending=False, pct=True).loc[x.name]*100,1) if x['col']<0 else np.nan), axis=1 )
内容的提问来源于stack exchange,提问作者John Holmes
相关产品推荐
相关产品推荐

