使用Power BI在Python上遍历数据框以生成新的数据框

时间:2019-07-29 21:17:40

标签: python pandas dataframe iteration

在将视觉效果输入报表之前,在Power BI中使用python处理数据。

我正在做的事的例子:

采购订单数据库来自oracle。 供应数据库来自多个位置(SQL / csv)。

购买订单X需要20个单位的a / 30个单位的b(例如)

我已经将其与下面的代码一起使用-但是我尚未在完整的数据集上运行它-我访问的所有线程基本上都说我这样做的方式并不理想-我很好奇有一种更简单,更节省内存的方式来完成此任务。

I / o源是PBI中的pandas数据帧-据我所知,它还支持numpy和其他几个。

下面的代码显示了我目前的工作方式-在500个左右的样本量上它可以非常快速地工作-需要确保我可以按比例放大。

下面的示例使用2个数据帧:(df1是需求表,df2是供应表)以按订单分配供应物料)df3是用于存储计算的临时数组。

要进一步澄清-主要关注的问题是iterrows(),而该关注纯粹基于我已阅读的内容(主要是在此站点上)

编辑:非常感谢您抽出宝贵时间阅读和帮助我! https://stackoverflow.com/users/10239974/eva-vw

不确定如何添加输出,但这是数据的外观(图片中)df1

df2

我不认为我可以合并它们,因为df1中的Alloy标签是一个需求值,而df2中的Alloy标签是一个库存值-如果可以的话,这太棒了-我会尝试一下让您的代码你懂!再次谢谢你。

哦,最后一个细节-我创建的“ Counter”列只是将索引保持在需求所在的位置-当我在没有它的情况下执行相同的代码时,最终合并成最终df4的我的df3只有那么多行,只要我分配的订单行长-我希望它与df1保持一致,以便我可以将它们放在一起-当我为每次迭代在其中添加一个值时,它会保留正确的位置。 Df3就像Counter :, Allocated一样结束,然后将其添加到DF1中,以便Lbs(必需)和Allocation与订单一起。

编辑:切换到df1合并后的最终输出:df1 with merge https://stackoverflow.com/users/10239974/eva-vw

编辑:使用原始代码iterrows()的最终输出:df4:df4 https://stackoverflow.com/users/10239974/eva-vw

编辑:具有调整功能的最终输出:df1adjusted https://stackoverflow.com/users/10239974/eva-vw

要进一步解释-库存中有53000磅的这种成分-因此一旦库存量过大,它就会停止分配-但是我想我可以理解这一点,因为我理解了你的逻辑。

顺便说一句-您的代码立即执行-在迭代加载大约一秒钟的时间内-因此从扩展角度来看,我对此感到非常兴奋!

import pandas as pd
df1 = pd.DataFrame.from_dict({'Name': ['a','b','c'], 'Alloy': ['R80','R80','R80'], 'Lbs': [6400,6400,6400]})
df2 = pd.DataFrame.from_dict({'ITEM': ['R80'], 'Inv': [50000]})
df3 = pd.DataFrame()
df3["Allocated"] = ""
df3["Counter"] = ""
for i, row in df2.iterrows():
    x = df2.at[i, 'ITEM']
    y = df2.at[i, 'Inv']
    g = 0
    for j, row in df1.iterrows():
        g+=1
        df3.at[j, 'Counter'] = g
        if df1.at[j, 'Alloy'] == x:
            z = df1.at[j, 'Lbs']
            if y >= z:
                df3.at[j, 'Allocated'] = z
                y = y - z
            else:
                break

df4 = pd.concat([df1,df3],axis=1)

1 个答案:

答案 0 :(得分:0)

最好获取您的输入数据样本(仅df.head()起作用),并使用列名对计算进行更详细的说明。

这是否复制您的逻辑?这消除了您的循环之一。如果您确认这是您想要做的,我们可以考虑如何加快速度。

# merge ITEM and Inv info from df2 into df1 based on overlap between Alloy and ITEM
df1 = df1.merge(df2[['ITEM', 'Inv']], how='left', left_on=['Alloy'], right_on=['ITEM'])
# set base allocation to Inv
df1['Allocated'] = df1['Inv']

def subtract_lbs(row):
    item = row['ITEM']
    allocated = row['Allocated']
    lbs = row['Lbs']
    if allocated >= lbs:
        remaining = allocated-lbs
        df1.loc[df1['ITEM'] == item, 'Allocated'] = remaining
        return remaining
    else:
        return allocated

# iteratively subtract lbs from allocated
df1['Allocated'] = df1.apply(subtract_lbs, axis=1)

编辑:上面的方法确实正确更新了df1 ['Allocated'],因为在执行df1.apply时df1.loc不会产生预期的行为。使用临时df。

# merge ITEM and Inv info from df2 into df1 based on overlap between Alloy and ITEM
df1 = df1.merge(df2[['ITEM', 'Inv']], how='left', left_on=['Alloy'], right_on=['ITEM'])
# create temporary dataframe for the calculation
temp_df = df1.copy()
# set base allocation to Inv
temp_df['Allocated'] = temp_df['Inv']

def subtract_lbs(row):
    item = row['ITEM']
    lbs = row['Lbs']
    allocated = temp_df.loc[temp_df['ITEM'] == item, 'Allocated'].values[0]
    if allocated >= lbs:
        remaining = allocated-lbs
        temp_df.loc[df1['ITEM'] == item, 'Allocated'] = remaining
        return remaining
    else:
        return allocated

# iteratively subtract lbs from allocated
df1['Allocated'] = df1.apply(subtract_lbs, axis=1)