根据列值复制行并修改列值

问题描述

此问题是对this其他问题的跟进。 为了方便起见,我使用相同的示例。

# dictionary of transactions
d = {
    '1': ['20','NYC','2'],'2': ['30','3': ['5','4': ['300','LA','5': ['30','6': ['100','2']
}
columns=['Price','City','Quantity']
# create dataframe and rename columns
df = pd.DataFrame.from_dict(
    data=d,orient='index'
)
df.columns = columns

结果数据帧如下:

Price   City    Quantity
20       NYC         2
30       NYC         2
5        NYC         2
300      LA          2
30       LA          2
100      LA          2

我想基于“数量”来复制行,但我也想修改数量”列,以使每行代表给定价格和城市的第n个元素。

df_new = pd.DataFrame([pd.Series([df.loc[idx,"Price"],df.loc[idx,"City"],"Quantity"]-r-1])
                       for idx in df.index
                       for r in range(df.loc[idx,'Quantity'])]).reset_index(drop=True)

这是预期的结果:

      0    1  2
0    20  NYC  0
1    30  NYC  1
2    30  NYC  0
3     5   SF  2
4     5   SF  1
5     5   SF  0
6   300   LA  0
7    30   LA  1
8    30   LA  0
9   100   SF  2
10  100   SF  1
11  100   SF  0

上面的代码可以用,但是看起来很慢,而且不大熊猫。 另外,由于我必须为每一行重新创建系列,所以现在我需要重命名数据框列。

有更好的方法吗?

解决方法

Index.repeat用于索引值,按DataFrame.loc获取新行,最后将GroupBy.cumcountascending=False使用:

df_new = df.loc[df.index.repeat(df['Quantity'])]
df_new['Quantity'] = df_new.groupby(level=0).cumcount(ascending=False)
df_new = df_new.reset_index(drop=True)
print (df_new)
    Price City  Quantity
0      20  NYC         1
1      20  NYC         0
2      30  NYC         1
3      30  NYC         0
4       5  NYC         1
5       5  NYC         0
6     300   LA         1
7     300   LA         0
8      30   LA         1
9      30   LA         0
10    100   LA         1
11    100   LA         0