在分析数据时,有时需要得到所有可能的二维组合。一种情况是,事件数据作为一个数据集,时间数据作为另一个数据集。这可能发生在金融交易、web事件和许多其他领域。可能有些时间段不包括任何事件。如果你想分析每一个时间段的数据这些空白的时间段需要被填充。
在panda中实现此功能的一种方便方法是使用MultiIndex.from_product函数。此函数将在两个或多个迭代元素之间创建所有可能组合的集合。下面是在两个短列表上使用该函数的Python示例。
import pandas as pd
basic_index = pd.MultiIndex.from_product([[1, 2, 3], ['a', 'b', 'c']])
print(basic_index.values)
[(1, 'a') (1, 'b') (1, 'c') (2, 'a') (2, 'b') (2, 'c') (3, 'a')(3, 'b') (3, 'c')]
输出显示为两个列表中的每个可能元素组合创建了索引条目。
我们现在看一个示例,它显示了更实用的用法。假设我们正在经营一家可以从重复客户那里获得定期订单的业务。我们的原始订单数据看起来像这样:
from datetime import datetime
import pandas as pd
orders = pd.DataFrame(
data={
'customer': [1, 2, 3, 2, 3, 1, 1],
'order_date': [
datetime(2018, 1, 3),
datetime(2018, 1, 5),
datetime(2018, 1, 7),
datetime(2018, 1, 8),
datetime(2018, 1, 9),
datetime(2018, 1, 10),
datetime(2018, 1, 10)
],
'amount': [25, 42, 116, 21, 83, 4, 67]
}
)
print(orders)
一个有用的报告是每个客户每月运行的订单总数。尽管该cumsum功能可以轻松地为我们提供总计,但首先需要克服几个问题:
某些日期 - 客户组合在数据中出现不止一次。这些必须在计算每日运行总量之前进行汇总。
缺少许多date-customer组合。这些将需要填充。
第一个问题是直截了当地解决。金额只需要按日期和客户加总。第一个问题是直接解决的。金额只需要按日期和客户汇总即可。
daily_orders = orders.groupby(['customer', 'order_date']).sum()
print(daily_orders)
第二个问题需要我们建立一个MultiIndex。这将通过创建唯一客户列表并使用from_product 2018-01-01和2018-01-10之间的日期范围交叉加入来完成。
unique_customers = daily_orders.index.unique(level='customer')
date_range = pd.DatetimeIndex(
start=datetime(2018, 1, 1),
end=datetime(2018, 1, 10),
freq='D'
)
customer_date_index = (
pd.MultiIndex
.from_product(
iterables=[unique_customers, date_range],
names=['customer', 'order_date']
)
)
print(customer_date_index.values[:5])
[(1, Timestamp('2018-01-01 00:00:00', freq='D'))
(1, Timestamp('2018-01-02 00:00:00', freq='D'))
(1, Timestamp('2018-01-03 00:00:00', freq='D'))
(1, Timestamp('2018-01-04 00:00:00', freq='D'))
(1, Timestamp('2018-01-05 00:00:00', freq='D'))]
这段代码创建了一个MultiIndex ,其中包含日期范围内的每个客户和每个日期的组合。即使没有订单的客户和日期组合也会出现。下一步是用新索引重新索引现有的订单数据,以便填充所有的日期空白。结果数据将按照客户和使用cumsum计算的运行总数进行分组。
daily_orders = daily_orders.reindex(customer_date_index, fill_value=0)
daily_orders['running_amount'] = (
daily_orders
.reindex()
.groupby('customer')
.cumsum()
)
print(daily_orders)
最终结果显示,每个客户在整个日期范围内都有每日运行总量。
这只是该MultiIndex.from_product函数如何帮助您将稀疏数据转换为完全填充数据集的一个示例。