使用 Pandas 数据帧查找多个索引上所有列之间的差异(增量)
Posted
技术标签:
【中文标题】使用 Pandas 数据帧查找多个索引上所有列之间的差异(增量)【英文标题】:Find difference (delta) between all columns over multiple indexes using Pandas dataframes 【发布时间】:2021-02-05 17:25:30 【问题描述】:以以下为例:
import datetime
import pandas as pd
data = [
"date": datetime.date(2020, 1, 1), "product": "product_1", "price": 90, "quantity": 100, "code": "code-1.1",
"date": datetime.date(2020, 1, 1), "product": "product_2", "price": 80, "quantity": 80, "code": "code-2.1",
"date": datetime.date(2020, 1, 1), "product": "product_3", "price": 80, "quantity": 80, "code": "code-3.1",
"date": datetime.date(2020, 1, 2), "product": "product_1", "price": 90, "quantity": 80, "code": "code-1.1",
"date": datetime.date(2020, 1, 2), "product": "product_2", "price": 80, "quantity": 80, "code": "code-2.1",
"date": datetime.date(2020, 1, 2), "product": "product_3", "price": 80, "quantity": 80, "code": "code-3.1",
"date": datetime.date(2020, 1, 3), "product": "product_1", "price": 90, "quantity": 80, "code": "code-1.1",
"date": datetime.date(2020, 1, 3), "product": "product_2", "price": 80, "quantity": 80, "code": "code-2.2",
"date": datetime.date(2020, 1, 4), "product": "product_1", "price": 80, "quantity": 70, "code": "code-1.1",
"date": datetime.date(2020, 1, 4), "product": "product_2", "price": 70, "quantity": 80, "code": "code-2.2",
"date": datetime.date(2020, 1, 4), "product": "product_3", "price": 80, "quantity": 80, "code": "code-3.1",
]
df = pd.DataFrame(data)
df = df.set_index(["date", "product"])
希望我能够在每个非索引列上产生差异/增量,并且只输出更改的列并且不输出没有任何变化的天数,但还要确定何时错过了天数,然后第二天输出该日期/产品的所有列。
一个示例输出是:
"date": datetime.date(2020, 1, 1), "product": "product_1", "price": 90, "quantity": 100, "code": "code-1.1",
"date": datetime.date(2020, 1, 1), "product": "product_2", "price": 80, "quantity": 80, "code": "code-2.1",
"date": datetime.date(2020, 1, 1), "product": "product_3", "price": 80, "quantity": 80, "code": "code-3.1",
"date": datetime.date(2020, 1, 2), "product": "product_1", "price": None, "quantity": 80, "code": None,
"date": datetime.date(2020, 1, 3), "product": "product_2", "price": None, "quantity": None, "code": "code-2.2",
"date": datetime.date(2020, 1, 4), "product": "product_1", "price": 80, "quantity": 70, "code": None,
"date": datetime.date(2020, 1, 4), "product": "product_2", "price": 70, "quantity": None, "code": None,
"date": datetime.date(2020, 1, 4), "product": "product_3", "price": 80, "quantity": 80, "code": "code-3.1",
澄清以上内容:
对于product_1
:日期 2020-01-03 缺失,因为列(价格、数量)中没有任何变化 - 而对于日期 2020-01-02,价格为 None
,因为它没有变化。
对于product_2
:日期 2020-01-01 由于是第一个数据点而存在,代码在 2020-01-03 更改,价格在 2020-01-04 更新。
对于product_3
:日期 2020-01-01 由于是第一个数据点而存在,日期 2020-01-04 由于上一个日期 (2020-01-03) 而存在,我们没有任何数据那天。
我曾尝试对数据框进行迭代,但担心扩展速度会很慢。我觉得像pct_change
这样的东西会起作用,但是从阅读这对多索引来说就不起作用了。
同样,答案也反映了 diff 可以在 int
列上工作,但是我理想情况下也需要这个也可以在 str
列上工作。
【问题讨论】:
您可以使用df['price']-df['price'].shift(-1)
例如获取从一天到下一天的价格差异,然后使用 nonzero 获取列不为零的索引以进行删除或屏蔽跨度>
@G.Anderson 但我想在多个列(价格和数量)上执行此操作,并且将来会在更多列上执行此操作。
【参考方案1】:
对于单个产品
diffs = df.diff()
df[diffs == 0] = None
df[~(diffs == 0).all(axis=1)]
price quantity
date product
2020-01-01 product_1 90.0 100.0
2020-01-02 product_1 NaN 80.0
2020-01-04 product_1 80.0 70.0
适用于多种产品
def show_diffs(df):
diffs = df.diff()
df[diffs == 0] = None
return df[~(diffs == 0).all(axis=1)]
df.groupby('product').apply(show_diffs).sort_values('date')
price quantity
product date product
product_1 2020-01-01 product_1 90.0 100.0
product_2 2020-01-01 product_2 80.0 80.0
product_1 2020-01-02 product_1 NaN 80.0
2020-01-04 product_1 80.0 70.0
product_2 2020-01-04 product_2 70.0 NaN
【讨论】:
如果只有一个产品,这可以工作,如果有多个产品,这将如何工作? 这取决于您的数据框如何存储产品信息。如果您在同一列中有“product_1”、“product_2”等,那么您可能可以使用groupby
构造它们并将上述步骤作为函数传递。
@MarcusChaplais 添加了 groupby 解决方案
看起来不错!如果我添加一个只处理字符串的列,这将如何工作?例如product_code
,它可能会随着时间的推移而改变,我也想有一个差异?据我了解.diff()
只处理数字。
也许从它创建int
列并使用它? df['product_code'] = df.index.get_level_values('product').str[-1].astype(int)
.以上是关于使用 Pandas 数据帧查找多个索引上所有列之间的差异(增量)的主要内容,如果未能解决你的问题,请参考以下文章
Pandas:使用循环和分层索引将多个 csv 文件导入数据帧
使用 pandas 或 numpy 从一个 csv 加载多个数据帧