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

如何按r_count扩展DataFrame并随机分配col值至value_1列

Python Pandas: Expand Rows by Count and Distribute Column Value Randomly

问题回顾

你有一个原始DataFrame df1,需要生成新的df2满足以下要求:

  • 按每行的r_count值扩展对应行(比如第一行扩展为22条记录)
  • 新增value_1列,所有扩展行的value_1总和等于原行的col值,且为随机分配而非均分
  • 其余列保持与df1一致

原始df1的数据可通过以下代码构造:

import pandas as pd

data = {
    'F_Date': ['01/09/2019']*13,
    'Booking_Date': ['02/08/2019', '03/08/2019', '04/08/2019', '06/08/2019', '09/08/2019', 
                     '10/08/2019', '11/08/2019', '12/08/2019', '13/08/2019', '14/08/2019', 
                     '15/08/2019', '16/08/2019', '17/08/2019'],
    'col': [70,73,76,79,82,86,89,93,97,101,106,110,115],
    'r_count': [22,12,9,6,5,4,4,4,4,4,3,3,4]
}
df1 = pd.DataFrame(data)

解决方案

我提供两种实现方式,第一种简洁高效,第二种可以严格保证value_1总和与原col值完全相等(避免浮点误差)。

方法一:简洁版(随机分配,总和近似相等)

这种方法利用numpy生成随机数并归一化,快速实现需求:

import numpy as np

def expand_row(row):
    # 生成r_count个0-1之间的随机数
    random_vals = np.random.rand(row['r_count'])
    # 归一化处理,让随机数总和等于原行的col值
    normalized_vals = random_vals / random_vals.sum() * row['col']
    # 构造扩展后的行数据
    return pd.DataFrame({
        'F_Date': [row['F_Date']]*row['r_count'],
        'Booking_Date': [row['Booking_Date']]*row['r_count'],
        'col': [row['col']]*row['r_count'],
        'r_count': [row['r_count']]*row['r_count'],
        'value_1': normalized_vals
    })

# 应用函数到每一行并合并结果
df2 = pd.concat(df1.apply(expand_row, axis=1).tolist(), ignore_index=True)

说明:

  • np.random.rand()生成的随机数分布均匀,归一化后可以保证总和接近原col值(因为浮点精度问题可能有极小误差)
  • 这种方法代码简洁,适合对精度要求不是极高的场景

方法二:严格精度版(总和完全等于col)

如果需要value_1的总和严格等于原col值,且保留指定小数位数(比如两位),可以用这个方法:

def expand_row_precise(row):
    n = row['r_count']
    # 如果r_count为1,直接返回原col值
    if n == 1:
        return pd.DataFrame({
            'F_Date': [row['F_Date']],
            'Booking_Date': [row['Booking_Date']],
            'col': [row['col']],
            'r_count': [row['r_count']],
            'value_1': [row['col']]
        })
    
    # 生成n-1个随机数,归一化后调整总和小于col
    random_vals = np.random.rand(n-1)
    scaled_vals = random_vals / random_vals.sum() * (row['col'] - 0.01)  # 留余量避免溢出
    scaled_vals = scaled_vals.round(2)
    
    # 计算最后一个值,确保总和严格等于col
    last_val = row['col'] - scaled_vals.sum()
    last_val = round(last_val, 2)
    
    # 合并所有value_1值
    value_1 = np.append(scaled_vals, last_val)
    
    # 构造扩展后的行
    return pd.DataFrame({
        'F_Date': [row['F_Date']]*n,
        'Booking_Date': [row['Booking_Date']]*n,
        'col': [row['col']]*n,
        'r_count': [row['r_count']]*n,
        'value_1': value_1
    })

df2_precise = pd.concat(df1.apply(expand_row_precise, axis=1).tolist(), ignore_index=True)

说明:

  • 先生成前n-1个随机值,再通过计算得到最后一个值,确保总和严格等于原col值
  • 使用round(2)保留两位小数,符合常见的数值展示需求

验证结果

你可以通过以下代码验证value_1的总和是否符合要求:

# 验证某一行的value_1总和
sample_booking_date = '02/08/2019'
original_col = df1[df1['Booking_Date'] == sample_booking_date]['col'].values[0]
sum_value1 = df2_precise[df2_precise['Booking_Date'] == sample_booking_date]['value_1'].sum()

print(f"原col值: {original_col}, value_1总和: {sum_value1}")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:56:16