不使用循环的熊猫数据帧操作

时间:2020-02-20 18:17:23

标签: python-3.x pandas numpy

请找到以下输入和输出。对应于每个商店ID和期间ID,应该存在11个项目,如果缺少任何项目,请将其添加并用0填充该行 不使用循环

我们非常感谢您的帮助。

输入

enter image description here

预期产量

enter image description here

3 个答案:

答案 0 :(得分:1)

您可以这样做:

from itertools import product

pdindex=product(df.groupby(["store_id", "period_id"]).groups, range(1,12))

pdindex=pd.MultiIndex.from_tuples(map(lambda x: (*x[0], x[1]), pdindex), names=["store_id", "period_id", "Item"])

df=df.set_index(["store_id", "period_id", "Item"])

res=pd.DataFrame(index=pdindex, columns=df.columns)

res.loc[df.index, df.columns]=df

res=res.fillna(0).reset_index()

现在,这仅在假设您没有Item范围之外的任何[1,11]时才有效。

答案 1 :(得分:1)

您可以这样做:

样本df

df = pd.DataFrame({'store_id':[1160962,1160962,1160962,1160962,1160962,1160962,1160962,1160962,1160962,1160962, 1160962],
                   'period_id':[1025,1025,1025,1025,1025,1025,1026,1026,1026,1026,1026],
                   'item_x':[1,4,5,6,7,8,1,2,5,6,7],
                  'z':[1,4,5,6,7,8,1,2,5,6,7]})

解决方案:

num = range(1,12)
def f(x):
    return x.reindex(num, fill_value=0)\
                   .assign(store_id=x['store_id'].mode()[0], period_id = x['period_id'].mode()[0])

df.set_index('item_x').groupby(['store_id','period_id'], group_keys=False).apply(f).reset_index()

答案 2 :(得分:0)

这是@GrzegorzSkibinski正确答案的简化形式。

此答案未修改原始DataFrame。它使用较少的变量来存储中间数据结构,并使用列表推导简化了map的使用。

我还使用reindex(),而不是使用生成的索引创建新的DataFrame并将其填充原始数据。

import pandas as pd
import itertools

df.set_index(
    ["store_id", "period_id", "Item_x"]
).reindex(
    pd.MultiIndex.from_tuples([
        group + (item,)
        for group, item in itertools.product(
            df.groupby(["store_id", "period_id"]).groups, 
            range(1, 12),
        )],
        names=["store_id", "period_id", "Item_x"]
    ),
    fill_value=0,
).reset_index()

在测试中,输出符合您的预期。