You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

np.where结合pandas抽样赋值异常问题排查求助

问题分析与解决:np.where结合抽样赋值的逻辑错误

问题根源

你的代码存在两个核心逻辑错误,直接导致结果不符合预期:

  1. 两次np.where的赋值覆盖问题
    你先对Low_Valence行执行np.where赋值,紧接着又对High_Valence行执行第二次np.where。第二次赋值时,所有不满足High_Valence条件的行(也就是所有Low_Valence的行)都会被强制设为'High',直接覆盖了第一次的操作结果——这就是为什么你的示例里所有Low_Valence行的temp_selection都是'High'的原因。

  2. 抽样范围错误+reindex导致NaN
    你用df['valence_median_split'].sample(n=200)是从整个列随机抽样,而不是从Low_Valence或High_Valence的分组内抽样。之后用reindex(df.index)会把抽样得到的少量值放到原索引位置,其余位置都是NaN。当np.where把这些NaN赋值给Low_Valence行后,第二次np.where会把这些NaN行(属于Low_Valence)判定为不满足High_Valence条件,进而设为'High'。同时,抽样得到的High_Valence值会被错误地赋值给部分High_Valence行,导致出现不该有的'High_Valence'标记。

解决方法

正确的思路是:先分别从两个分组内抽取目标行数的索引,再基于索引给temp_selection赋值,避免覆盖和抽样范围错误。

步骤1:抽取分组内的目标索引

先从Low_Valence和High_Valence各自的行中随机选出200个(或示例中的2个)索引:

# 获取Low_Valence分组的所有索引
low_indices = df[df['valence_median_split'] == 'Low_Valence'].index
# 随机选200个(示例中选2个),replace=False确保不重复抽样
selected_low = np.random.choice(low_indices, size=200, replace=False)

# 同理处理High_Valence分组
high_indices = df[df['valence_median_split'] == 'High_Valence'].index
selected_high = np.random.choice(high_indices, size=200, replace=False)

步骤2:基于索引赋值

先初始化temp_selection为默认值,再根据选中的索引修改对应位置的值,避免覆盖:

# 先给所有行设默认值:Low_Valence组默认'Low',High_Valence组默认'High'
df['temp_selection'] = np.where(df['valence_median_split'] == 'Low_Valence', 'Low', 'High')

# 把选中的Low_Valence行改为'Low_Valence'
df.loc[selected_low, 'temp_selection'] = 'Low_Valence'

# 把选中的High_Valence行改为'High_Valence'
df.loc[selected_high, 'temp_selection'] = 'High_Valence'

测试你的可复现示例

用你的小例子测试(size改为2):

d = {'col1': [1, 2, 3, 4, 3, 3, 2, 2], 'col2': [1, 2, 3, 4, 3, 3, 2, 2]}
df = pd.DataFrame(data=d)
valence_median = df['col1'].median()
df['valence_median_split'] = np.where(df['col2'] < valence_median, 'Low_Valence', 'High_Valence')

# 抽取索引
low_indices = df[df['valence_median_split'] == 'Low_Valence'].index
selected_low = np.random.choice(low_indices, size=2, replace=False)
high_indices = df[df['valence_median_split'] == 'High_Valence'].index
selected_high = np.random.choice(high_indices, size=2, replace=False)

# 赋值
df['temp_selection'] = np.where(df['valence_median_split'] == 'Low_Valence', 'Low', 'High')
df.loc[selected_low, 'temp_selection'] = 'Low_Valence'
df.loc[selected_high, 'temp_selection'] = 'High_Valence'

print(df)

执行后会得到符合预期的结果:Low_Valence组里有2行标记为'Low_Valence',其余为'Low';High_Valence组里有2行标记为'High_Valence',其余为'High',不会出现NaN或错误的标记。

补充说明

  • 如果你的分组行数不足200(比如Low_Valence只有150行),可以把replace=True打开(允许重复抽样),或者根据实际行数调整抽样数量。
  • 用np.random.choice比直接用sample更灵活,能直接拿到索引,方便后续的loc赋值操作。

内容的提问来源于stack exchange,提问作者arkadiy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:51:02