Pandas 数据框,比较多个数据框的加权值

Pandas dataframe, comparing weighted values across multiple dataframes

我正在尝试对 3 个或更多不同的数据帧进行加权求和。

3 个数据帧中的每一个都具有相同的形式。

df1 = pd.DataFrame([
    {'rowid':1,'predict1': 'choice1', 'predict2': 'choice2', 'predict3': 'choice3'},
    {'rowid':2,'predict1': 'choice4', 'predict2': 'choice5', 'predict3': 'choice1'},
])

df2 = pd.DataFrame([
    {'rowid':1,'predict1': 'choice1', 'predict2': 'choice3', 'predict3': 'choice4'},
    {'rowid':2,'predict1': 'choice1', 'predict2': 'choice5', 'predict3': 'choice4'},
])

df3 = pd.DataFrame([
    {'rowid':1,'predict1': 'choice2', 'predict2': 'choice3', 'predict3': 'choice1'},
    {'rowid':2,'predict1': 'choice4', 'predict2': 'choice1', 'predict3': 'choice6'},
])

我正在尝试使用此数据进行统计(基于给定数据帧的权重和给定预测的权重。例如,每个数据帧的权重可能是:

weights_dataframe = { 'df1': 1.1, 'df2': 1.2, 'df3': 0.9 }
weights_predictions= { 'predict1': 1.0, 'predict2': 0.5, 'predict3': 0.333 }

每一行都有一个基于所有数据帧的单独计数。例如,'choice1'、'rowid':1 的计数为:

tally_row1_choice1 = 1.1*1.0 + 1.2*1.0 + 0.9*0.333

基于此操作,我正在尝试生成一个新的数据框结果,该结果将显示前 3 个选择(最高总和到第三高总和)。

理想情况下,我想做这样的事情:

tally = getTop3ForEachRow(df1,df2,df3)

result = pd.DataFrame([
    {'rowid':1, 'predict1': tally[0][0], 'predict2': tally[0][1], 'predict3': tally[0][2] },
    {'rowid':2, 'predict1': tally[1][0], 'predict2': tally[1][1], 'predict3': tally[1][2] }
]) 

实现 getTop3ForEachRow() 的 pythonic 方式是什么?是否可以将其作为数据框公式来执行? numpy 是否适合处理此类制表?

解决方案

def getTop3ForEachRow(df1, df2, df3):

    df = pd.concat([d.set_index('rowid') for d in [df1, df2, df3]],
                   keys=['df1', 'df2', 'df3'])

    wghts_df = pd.DataFrame([1.1, 1.2, 0.9], ['df1', 'df2', 'df3'])
    wghts_pr = pd.DataFrame([1.0, 0.5, 0.333], ['predict1', 'predict2', 'predict3']).T
    wghts = wghts_df.dot(wghts_pr)

    wghts_by_group = df.groupby(level='rowid').apply(lambda x: wghts).unstack(0).stack()
    bdf = pd.concat([df, wghts_by_group], axis=1, keys=['choices', 'weights'])

    bdf1 = bdf.stack().set_index('choices', append=True)
    bdf2 = bdf1.groupby(level=[1, 3]).sum().unstack(0)
    sort = lambda x: x.sort_values(ascending=False).index
    return bdf2.apply(sort).reset_index(drop=True).head(3).values.T

示范[​​=13=]
tally = getTop3ForEachRow(df1, df2, df3)

result = pd.DataFrame([
    {'rowid':1, 'predict1': tally[0][0], 'predict2': tally[0][1], 'predict3': tally[0][2] },
    {'rowid':2, 'predict1': tally[1][0], 'predict2': tally[1][1], 'predict3': tally[1][2] }
]) 

print result

  predict1 predict2 predict3  rowid
0  choice1  choice2  choice3      1
1  choice4  choice1  choice5      2

说明

def getTop3ForEachRow(df1, df2, df3):
    # concat all 3 dataframes one after the other while setting
    # the rowid as the index
    df = pd.concat([d.set_index('rowid') for d in [df1, df2, df3]],
                   keys=['df1', 'df2', 'df3'])

    # wghts_df is a column, wghts_pr is a row.
    # the dot product with give all cross multiplied values.
    wghts_df = pd.DataFrame([1.1, 1.2, 0.9], ['df1', 'df2', 'df3'])
    wghts_pr = pd.DataFrame([1.0, 0.5, 0.333], ['predict1', 'predict2', 'predict3']).T
    wghts = wghts_df.dot(wghts_pr)

    # I just want to set all cross multiplied weights side
    # by side with each rowid
    wghts_by_group = df.groupby(level='rowid').apply(lambda x: wghts).unstack(0).stack()
    bdf = pd.concat([df, wghts_by_group], axis=1, keys=['choices', 'weights'])

    # pivot ['predict1', 'predict2', 'predict3'] into index
    # append to index, 'choices'
    bdf1 = bdf.stack().set_index('choices', append=True)
    # groupby rowid and choices
    bdf2 = bdf1.groupby(level=[1, 3]).sum().unstack(0)
    # sort descending, take index value (the choice) take top 3
    sort = lambda x: x.sort_values(ascending=False).index
    return bdf2.apply(sort).reset_index(drop=True).head(3).values.T