根据条件将记录拆分为两个记录并进行计算

2 投票
2 回答
42 浏览
提问于 2025-04-14 16:30

如标题所示,假设我有以下的数据表

import pandas as pd


df = pd.DataFrame({'UID':['A','B','C','D'],'FlagVal':[0,100,50,90],'TrueVal':[1000,1000,1000,1000]})
ndf = df.loc[~df['FlagVal'].between(0,100,inclusive='neither')]
mdf = df.loc[df['FlagVal'].between(0,100,inclusive='neither')]

我想把记录分成两部分,其中 FlagVal 的值在 0 到 100 之间。也就是说,生成一个叫 mdf 的数据表,并进行一些计算 -

def split_record(row):
    gtd = row.copy()
    ungtd = row.copy()
    gtd['UID'] = row['UID'] + '_T1'
    gtd['Flag'] = 'Y'
    ungtd['UID'] = row['UID'] + '_T2'
    ungtd['Flag'] = ''
    
    gtd['TrueVal'] = float(gtd['TrueVal'])*(float(gtd['FlagVal'])/100.0)
            
    ungtd['TrueVal'] = float(ungtd['TrueVal'])*(1 - (float(ungtd['FlagVal'])/100.0))
    
    gtd['FlagVal'] = 100
    ungtd['FlagVal'] = 0
    result_data = pd.DataFrame([gtd, ungtd])
    
    return result_data


split_df = pd.concat([split_record(row) for _, row in mdf.iterrows()], ignore_index=True)

然后再和另一个叫 'ndf' 的数据表合并。对于大约1000条记录,这样做没问题,但当记录数量达到几百万时,就会变得很慢。我尝试使用 apply 函数,设置 axis=1,但不太确定如何再把结果和数据合并。

你能告诉我一个合适的函数来优化这个过程吗?

2 个回答

1

在编程中,有时候我们需要让程序在特定的条件下执行某些操作。比如说,当用户点击一个按钮时,我们希望程序能做出反应。这种情况就需要用到“事件处理”。

事件处理就是程序监听用户的操作,比如点击、输入等,然后根据这些操作来执行相应的代码。想象一下,你在玩一个游戏,按下某个键后,角色就会跳起来,这就是事件处理在起作用。

通常,我们会为每个事件设置一个“处理函数”,这个函数里写着当事件发生时要做的事情。比如,点击按钮后,可能会弹出一个消息框,告诉你“按钮被点击了”。

总之,事件处理让程序能够对用户的操作做出反应,从而使得程序更加互动和友好。

def split_record_df(df):
    gtd = df.copy()
    ungtd = df.copy()
    gtd['UID'] = df['UID'] + '_T1'
    gtd['Flag'] = 'Y'
    ungtd['UID'] = df['UID'] + '_T2'
    ungtd['Flag'] = ''
    
    gtd['TrueVal'] = gtd['TrueVal']*(gtd['FlagVal']/100.0)
            
    ungtd['TrueVal'] = ungtd['TrueVal']*(1 - (ungtd['FlagVal']/100.0))
    
    gtd['FlagVal'] = 100
    ungtd['FlagVal'] = 0
    result_data = pd.concat([gtd, ungtd])
    
    return result_data

split_df = split_record_df(df)
1

你可以用两个步骤来创建 split_df(这样做会非常快):

# create the 100% part:
mdf_100 = pd.DataFrame({"TrueVal": mdf["FlagVal"].div(100) * mdf["TrueVal"]}).assign(
    FlagVal=100, UID=mdf["UID"] + "_T1", Flag="Y"
)

# create the 0% part:
mdf_0 = pd.DataFrame(
    {"TrueVal": (1 - mdf["FlagVal"].div(100)) * mdf["TrueVal"]}
).assign(FlagVal=0, UID=mdf["UID"] + "_T2", Flag="")

split_df = pd.concat([mdf_100, mdf_0]).sort_index()

print(split_df)

输出结果:

   TrueVal  FlagVal   UID Flag
2    500.0      100  C_T1    Y
2    500.0        0  C_T2     
3    900.0      100  D_T1    Y
3    100.0        0  D_T2     

补充说明:如果有多个 TrueValX 列的话:

cols = ["TrueVal1", "TrueVal2", "TrueVal3"]

# create the 100% part:
mdf_100 = pd.DataFrame({c: mdf["FlagVal"].div(100) * mdf[c] for c in cols}).assign(
    FlagVal=100, UID=mdf["UID"] + "_T1", Flag="Y"
)

# create the 0% part:
mdf_0 = pd.DataFrame({c: (1 - mdf["FlagVal"].div(100)) * mdf[c] for c in cols}).assign(
    FlagVal=0, UID=mdf["UID"] + "_T2", Flag=""
)

split_df = pd.concat([mdf_100, mdf_0]).sort_index()

print(split_df)

输出结果:

   TrueVal1  TrueVal2  TrueVal3  FlagVal   UID Flag
2     500.0    1000.0    1500.0      100  C_T1    Y
2     500.0    1000.0    1500.0        0  C_T2     
3     900.0    1800.0    2700.0      100  D_T1    Y
3     100.0     200.0     300.0        0  D_T2     

输入的 df

  UID  FlagVal  TrueVal1  TrueVal2  TrueVal3
0   A        0      1000      2000      3000
1   B      100      1000      2000      3000
2   C       50      1000      2000      3000
3   D       90      1000      2000      3000

撰写回答