我的数据是什么样子
我用伦巴做了一些数值模拟。
输出是一组numpy数组;每个阵列表示一个度量,并且每个阵列具有形状(periods x items)
。
例如,metric_1[p,i]
告诉我metric_1在时间p
的值,用于项目i
。
每个项目属于某个类别-让我们说红色和绿色只是为了一个例子。一维数组categories
正好告诉我这一点-例如。categories[0]='a'
表示第一个项目属于类别a。从概念上讲,这就像将一个pandas多索引“展平”到另一个数组中。
我想做的是
1.我想按类别分组,并创建维度为(periods x categories)
的数组metric_1_grouped
,等等。
1.我想为每个类别创建一个数据框,并使用所有类别的总和创建一个数据框,其中每行是一个句点,每列是一个指标
这个问题本身是相当平庸的,但我的问题是**既然我必须多次这样做,那么什么是尽可能有效地完成这一任务的好方法呢?**一个典型的例子是:
- 300期
- 12个指标
- 50万件商品
- 6个类别
为什么我觉得这个问题不重复
我知道有几个问题在问numpy中是否有一个等价的groupby,例如。Is there any numpy group by function?,但它们是不同的,因为它们都由数组本身的元素分组。这不是我想做的-我需要分组,是的,但不是通过数组本身的任何元素,而是通过将列号与另一个数组相匹配。
有一些问题提到总结的基础上的立场,但如果我理解他们正确,他们不像我的情况下,例如。Map numpy array and sum values on positions in another array和sum array with condition in another array with numpy
- 请,请,非常请,不要关闭这个问题,除非你确定它已经在其他地方回答-有很多问题听起来相似,但不是 *。谢谢大家。
可能的解决方案?
- pandas Dataframe 多索引-但我担心它可能会慢得多
- itertools groupby?我承认我不是很熟悉
我试过的是--它能用,但不优雅,有点笨重
我下面的代码工作,但不优雅,有点笨重。我希望有一个更好/更优雅/更快的版本?
import numpy as np
import pandas as pd
num_periods = 300
num_items = 1000
# Let's suppose for simplicity that the data has already been sorted by category
categories = np.empty(num_items, dtype=object)
categories[0:100]='a'
categories[100:300]='b'
categories[300:600]='c'
categories[600:]='d'
rng = np.random.default_rng(seed=42) #setting a seed for reproducibility
metric_1 = rng.normal(0,1,(num_periods,num_items))
metric_2 = rng.uniform(0,1,(num_periods,num_items))
unique_categories = np.unique(categories)
num_categories=len(unique_categories)
where_to_split = np.unique(categories, return_index=True)[1][1:]
# The second item of the tuple returned by np.unique is an array with the
# indices of the categores (which, remember, we had already sorted - this is
# a requirement),
# so it will be: [0, 100, 300. 600]
# so where_to_split is an array which is [100, 300, 600]
metric_1_list = np.split(metric_1, where_to_split, axis=1)
metric_1_by_category = np.zeros((num_periods, num_categories))
for i in range(len(metric_1_list)):
metric_1_by_category[:,i] = metric_1_list[i].sum(axis=1)
metric_2_list = np.split(metric_2, where_to_split, axis=1)
metric_2_by_category = np.zeros((num_periods, num_categories))
for i in range(len(metric_2_list)):
metric_2_by_category[:,i] = metric_2_list[i].sum(axis=1)
# we now create a dictionary of dataframes
# df_by_cat['a'] will be the dataframe for categiry a, etc
df_by_cat = {}
for my_count, my_val in enumerate(unique_categories):
df_by_cat[my_val] = pd.DataFrame(index = np.arange(0,num_periods), columns=['metric 1','metric 2'])
df_by_cat[my_val]['metric 1'] = metric_1_by_category[:,my_count]
df_by_cat[my_val]['metric 2'] = metric_2_by_category[:,my_count]
2条答案
按热度按时间rggaifut1#
也许你可以用途:
输出:
您可以使用
pd.concat
连接所有 Dataframe :和玩
.T
,.stack
,pivot
等来重塑你的 Dataframe 。kr98yfug2#
我认为Pandas在不平衡类别上的groupby比np. split更好。您可以使用for循环对单独的指标进行groupby,因为您只有相对少量的指标。在这种情况下,您实际上不需要多索引。或者,你可以将所有数据连接到一个多索引的 Dataframe 中,并执行groupby,并拥有一个集中的 Dataframe ,而不是它们的列表/字典。
让我们尝试第二种方法:
那么前5个周期看起来像这样:
现在,假设您想要
metric_1
的数据,您可以执行以下操作:然后你会得到(前5个周期):
更新:由于您的项目相对较多,指标较小,您可以对每个指标进行分组,如:
然后
out
看起来像:并且用于特定度量的数据可以是:
输出:
更新2:numpy groupby功能在您的示例中是
np.sum.reduce_at