我的数据框包含每个用户ID的多变量时间序列。第一列id
是用户id(有N个用户),第二列dt
是日期(每个用户有T天的数据,即每个用户有T行),其他列是指标(基本上,每列是每个id的时间序列)。下面是重新创建类似 Dataframe 的代码
import pandas as pd
from datetime import datetime
import numpy as np
N=5
T=100
dfs=[]
datelist = pd.date_range(datetime.today(), periods=T).tolist()
for id in range(N):
test = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
test['dt'] = datelist
test['id']=id
dfs.append(test)
dfs = pd.concat(dfs)
字符串
输出结果如下所示,其中'A','B'等是指标(如总购买量):
| | C类|D级|dt|标识符| dt | id |
| --|--|--|--|--|--| ------------ |
| 五十八|三个|五十二|五个|2023-07-05 14:34:12.852460| 0个| 0 |
| 六个|三十四|二十八个|八十八个|2023-07-06 14:34:12.852460| 0个| 0 |
| 二十七|九十八|七十四|八十一|2023-07-07 14:34:12.852460| 0个| 0 |
| 九十六|十三个|七个|五十二|2023-07-08 14:34:12.852460| 0个| 0 |
| 八十|六十九|二十二|十二个|2023-07-09 14:34:12.852460| 0个| 0 |
我想把这个数据转换成一个numpy矩阵X,形状为N x T x F,其中N是用户数量,T是时间序列中的天数(T对所有id都是常数),F是度量的数量(在上面的例子中,F=4)。
这意味着X[0]返回一个TxF数组,它应该与dfs.query('id==0')[['A','B','C','D']].values
的输出完全相同
到目前为止,我已经尝试使用pivot
和reshape
,但最终矩阵中的元素并没有按照我想要的方式排列。以下是我尝试过的:
# Pivot the dataframe
df_pivot = dfs.sort_values(['id','dt']).pivot(index='id', columns='dt')
# Get the values from the pivot table
X = df_pivot.values.reshape(dfs['id'].nunique(), -1, len([x for x in dfs.columns if x not in ['dt','id']]))
型
如果我做X[0]
,结果是:
[58, 6, 27, 96],
[80, 65, 41, 39],
[30, 26, 38, 13],
[50, 60, 60, 73],
...
型
从中你可以看出结果不是我想要的。这就是我需要的:
[58, 3, 52, 5],
[ 6, 34, 28, 88],
[27, 98, 74, 81],
[96, 13, 7, 52],
...
型
任何帮助感谢!
4条答案
按热度按时间vnjpjtjt1#
注意,numpy数组将只包含类似形状的数组。
假设你可以这样做:
字符串
xwmevbvl2#
按id对dataframe进行分组,然后为每个唯一的id将指标导出为列表解析中的numpy数组
个字符
a5g8bdjr3#
如果您100%确定每个id都有完全相同的
T
个时间戳(而且,我猜它们是相同的时间戳,否则就没有意义了),则可以简单地字符串
请注意,我假设您知道
N
和F
。如果您不这样做,也可以使用T
。3个.reshape(N, T, F)
中的一个可以被-1
替换。无论如何,您都可以计算它们,即使您拥有的只是
dfs
型
后两种方法的计算速度比前一种方法慢。因此,使用
F
以及N
和T
中的一个来表示reshape
,如果有,最好使用您事先知道的那个。avkwfej44#
我添加了第二个答案,而不是编辑我的第一个答案,因为这个答案与我以前的答案完全不同,而且不仅仅是它的改进。
我之前的一个替代答案,灵感来自this one-关于大致相同的问题,但对于具有索引的 Dataframe ;但你必须这样做才能进入同样的境地
字符串
set_index
发送给我们链接问题的情况。to_xarray().to_array()
是这个问题的答案。因为它仍然不会返回numpy数组,所以
to_numpy()
会这样做。然后,由于它返回一个索引轴在末尾的3d数组,并且您希望首先使用
moveaxis
(无论如何,moveaxis
基本上是免费的)。它不移动任何数据)。一些时间对比
| 定时| Timing |
| --| ------------ |
| 5.2毫秒| 5.2 ms |
| 2.02毫秒| 2.02 ms |
| 索引然后排序)5.0 ms| 5.0 ms |
但是当缩放一点时(没有你在评论中说的那么多,N= 300 k。但是仅N= 5 k),定时改变
| 定时| Timing |
| --| ------------ |
| 142毫秒| 142 ms |
| 165毫秒| 165 ms |
| 625毫秒| 625 ms |
(缩放更多,不会改变这些比率,因为过了一段时间,所有3个方法都是O(N))。
所以在一定的大小之后,这种方法的成本不会超过基于
sort
的方法。Shubham's不能很好地扩展N轴,因为它是纯python复合列表(我还没有测试过,但我很确定它可以很好地沿着其他轴)
对缺失行的鲁棒性
它有一个巨大的优势:如果偶然地,其中一个id缺少一个时间戳,它仍然有效(用
nan
填充),而我的另一个答案以及Shubham的答案将失败,因为它们都依赖于每个id的行数相同。(我的sort
方法,因为reshape
假设正好有N×T×F值。或者,至少,用-1,因子T×F,但如果该因子不是N×T×F,则情况更糟:它看起来会起作用,但价值观会改变因为
np.array(...)
在2d数组的数组上假设所有这些数组具有相同的形状。当然,你说过是这样的。但是任何程序员在使用这种假设时都会感到不舒服。我们需要有点防御性。既然,无论如何,它不会花费更多,我会使用这种方法(我坚持“它不会花费更多”,因为我链接的旧帖子将其作为一种交易:成本更高,但更可靠;但是从那以后,就像其中一条评论中说的,
xarray
得到了改进。到了今天,这不是一个权衡。准确地说,如果我说“it doesn’t cost more”而不是跳到“it cost less”,那是因为在我做的随机计时中,有几次(5月1/4日),我的
sort/reshape
方法是最快的。但在另一个方向上,我们有同样的10%的利润率。所以现在,权衡不是关于时机。这是关于“需要100%肯定没有行丢失”与“需要一个包安装”(因为
.to_xarray()
需要一个pip install xarray
才能工作)。