压缩数据框中的类似实例,同时添加每个实例的功能

问题描述 投票:0回答:2

我正在使用Pandas开发一个项目,并且在尝试压缩类似对象时遇到了麻烦。

我有一个包含Product ID,Currency,Price和Book列的数据框。

产品ID类别中有相同的产品,例如X11,X23,X25等。每个实例有3个实例,每个实例有3种货币中的一种,有价格,有3本书中的一种。

我希望有一个数据框,其中每个实例都是一个产品,包含它们出现的任何书籍,以及每个实例中包含的4种货币的4种价格。

这是Dataframe现在的样子:

df = pd.DataFrame({'Product ID' : ['X11' ,'X11', 'X11', 'X23', 'X23', 'X23', 'X25', 'X25'], 
                    'Currency' : ['USD', 'EUR', 'GBP', 'USD', 'EUR', 'GBP', 'EUR', 'GBP'],
                    'Price' : [100, 90, 90, 200, 180, 180, 90, 90],
                    'Book' : ['America', 'Canada', 'Mexico', 'America', 'Canada', 'Mexico', 'Canada', 'Mexico']})


df

      Book Currency  Price Product ID
0  America      USD    100        X11
1   Canada      EUR     90        X11
2   Mexico      GBP     90        X11
3  America      USD    200        X23
4   Canada      EUR    180        X23
5   Mexico      GBP    180        X23
6   Canada      EUR     90        X25
7   Mexico      GBP     90        X25

最终它将转换为一个JSON文件,在一个实例中包含所有这些数据,但在此之前,我需要压缩相同的产品。请参阅下面的示例,了解最终JSON转换对象的外观。 enter image description here

实现这一目标的最佳方式是什么?我并不完全理解groupby,正如一些类似的问题所表明的那样,我还没有看到一个问题来解答如何做到这一点。一旦我有相同的产品只出现在一个实例中,但具有所有的价格和书籍数据,实际的转换本身不应该太难。

任何帮助深表感谢。

python pandas pandas-groupby
2个回答
1
投票

也可以使用for循环来创建所需的输出:

outlist = []                            # empty output list to be filled
uid = pd.unique(df['Product ID'])       # get unique ID values
for id in uid:
    subdf = df[df['Product ID'] == id]  # get sub-dataframe for one ID
    entry = {}                          # empty dictionary to be filled, one for each ID
    entry["Product Code"] = id          # add ID to dictionary
    entry["Book"] = ", ".join(subdf['Book'].tolist())   # add Book list to dictionary
    for row in subdf.values:            # get subdf as a list of lists
        entry[row[1]+" Price"] = row[2] # add prices to dictionary
    outlist.append(entry)               # add dictionary to outlist

print(outlist)

输出:

[{'Product Code': 'X11', 'GBP Price': 90, 'EUR Price': 90, 'USD Price': 100, 'Book': 'America, Canada, Mexico'}, 
 {'Product Code': 'X23', 'GBP Price': 180, 'EUR Price': 180, 'USD Price': 200, 'Book': 'America, Canada, Mexico'}, 
 {'Product Code': 'X25', 'GBP Price': 90, 'EUR Price': 90, 'Book': 'Canada, Mexico'}]

1
投票

您可以分两个阶段解决这个问题。

第一阶段需要3列pivot -

i = df.pivot('Product ID', 'Currency', 'Price')\
      .add_suffix(' Price')\
      .reset_index()\
      .rename_axis(None, 1)

i
  Product ID  EUR Price  GBP Price  USD Price
0        X11       90.0       90.0      100.0
1        X23      180.0      180.0      200.0
2        X25       90.0       90.0        NaN

接下来,在Product ID上执行groupby并汇总Book中的国家/地区名称 -

j = df.groupby('Product ID').Book.agg(', '.join).reset_index()
j

  Product ID                     Book
0        X11  America, Canada, Mexico
1        X23  America, Canada, Mexico
2        X25           Canada, Mexico

现在,合并两个中间结果 -

df = i.merge(j)
df

  Product ID  EUR Price  GBP Price  USD Price                     Book
0        X11       90.0       90.0      100.0  America, Canada, Mexico
1        X23      180.0      180.0      200.0  America, Canada, Mexico
2        X25       90.0       90.0        NaN           Canada, Mexico

现在,使用df格式的.to_jsonrecords转换为JSON -

df.to_json('file.json', orient='records')

file.json(输出)

[
    {
        "GBP Price": 90.0,
        "Book": "America, Canada, Mexico",
        "Product ID": "X11",
        "EUR Price": 90.0,
        "USD Price": 100.0
    },
    {
        "GBP Price": 180.0,
        "Book": "America, Canada, Mexico",
        "Product ID": "X23",
        "EUR Price": 180.0,
        "USD Price": 200.0
    },
    {
        "GBP Price": 90.0,
        "Book": "Canada, Mexico",
        "Product ID": "X25",
        "EUR Price": 90.0,
        "USD Price": NaN
    }
]
© www.soinside.com 2019 - 2024. All rights reserved.