在数据框中压缩相似的实例,同时添加每个实例的特征
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_json
以records
格式将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]
。以上是关于在数据框中压缩相似的实例,同时添加每个实例的特征的主要内容,如果未能解决你的问题,请参考以下文章