在数据框中压缩相似的实例,同时添加每个实例的特征

Posted

技术标签:

【中文标题】在数据框中压缩相似的实例,同时添加每个实例的特征【英文标题】:Condense similar instances in dataframe while adding the features of each 【发布时间】:2018-06-19 02:53:38 【问题描述】:

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

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

Product 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 转换对象的外观示例,请参见下文。

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

非常感谢任何帮助。

【问题讨论】:

df.to_json(orient='records') @cᴏʟᴅsᴘᴇᴇᴅ 我的问题更多是针对压缩相同的产品,同时保留所有不同的价格和书籍,而不是实际的 CSV 到 JSON 的转换。据我了解,现在进行该转换会导致产品具有相同 ID 的多个对象 对,我的误会。重新打开。 【参考方案1】:

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

第一阶段需要一个pivot 3 列 -

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 上执行分组并聚合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

现在,使用.to_jsonrecords 格式将df 转换为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
    
]

【讨论】:

@C0LDSPEED 非常感谢您的回答。当我尝试这个时,我收到错误“索引包含重复的条目,无法重塑”。 @AlexBozanic 抱歉,我已经纠正了几个错误。 再次感谢您的帮助。对这个新错误有些困惑。它是否使用产品 ID 作为索引,这就是它抛出该错误的原因? @AlexBozanic 你还在收到这个错误吗?如果有,在哪一行?你能提供一些数据来重现它吗? 我还是明白了。 Jupyter Notebook 说错误出现在第一行,即发生枢轴的地方。从概念上讲,整个过程是有意义的,我认为这是我一直在寻找的解决方案,现在我必须让它发挥作用。【参考方案2】:

也可以使用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']

【讨论】:

这似乎可行,但是我收到错误“+: 'float' 和 'str' 不支持的操作类型。它来自行 entry[row[1] +"Price"] = row[2]。你能提供任何关于如何摆脱它的指导吗? 打印一行并在​​此处发布。对我来说,第 [1] 行是英镑等,第 [2] 行是价格。 您的 row[1] 可能是 price 列,其中包含整数值,因此您会收到此错误。然后,您必须使用适当的索引编辑此行:entry[row[1]+" Price"] = row[2] 好的,为了完全清楚,我应该将哪些值更新为正确的索引?正确的指数是价格 entry[row[index_of_GBP_etc]+" Price"] = row[index_of_Price]。基本上,一个是在条目字典中创建一个键“GBP Price”并将其值分配为row[index_of_price]

以上是关于在数据框中压缩相似的实例,同时添加每个实例的特征的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中压缩 JSON 请求?

如何在Mac中压缩文件

如何将所有选定的文件添加到一个文件夹中并在php中压缩

我可以在 JavaScript 中压缩数据吗?

在 Apache Jena Fuseki 中压缩数据集

在 MSVC 中压缩后可能的数据损坏? (C++)