首页 > 解决方案 > 将数据帧转换为具有 n*n 结构的值的字典

问题描述

我在数据库中有一个看起来像这样的表

| day | x | y | value |
|---------------------|
| 0   | 0 | 1 |   20  |
| 0   | 1 | 2 |   20  |
| 0   | 3 | 3 |   20  |
| 1   | 0 | 0 |   20  |
| 1   | 0 | 3 |   20  |
| 1   | 2 | 2 |   20  |
| 1   | 3 | 1 |   20  |
| 1   | 3 | 3 |   20  |
| 2   | 2 | 1 |   20  |
| 2   | 2 | 2 |   20  |
| 2   | 0 | 0 |   20  |
| 2   | 3 | 1 |   20  |
| 2   | 0 | 3 |   20  |

基本上,在本例中,这是一个具有固定尺寸的区域上的传感器数据 3*3,但仪器并未覆盖整个空间。

我想创建一个看起来像这样的输出

{
  day0: {[[null, 20, null, 20], [null, 20, null, 20],[null, 20, null, 20],[null, 20, null, 20]]},
  day1: {[[null, 20, null, 20], [null, 20, null, 20],[null, 20, null, 20],[null, 1, null, 20]]},
  day2: {[[null, 20, null, 20], [null, 20, null, 20],[null, 20, null, 20],[null, 20, null, 20]]},
}

我目前通过创建一个包含所有空值的 3*3 numpy 矩阵来实现这一点,然后遍历数据集,用 x 和 y 值填充矩阵,然后转换为字典,但我认为这效率不高,因为它有一个 O( N) 时间复杂度。我已经尝试过 pandas pivot ,但是使用重复的索引(天)这是不可能的。如果可能的话,我想以更好的方式实现这一点,而不用循环使用熊猫。

Ps:这主要用于 plotly.js 中的绘图目的,因为这是 api 接受热图绘图的格式。

标签: pythonpandas

解决方案


我认为这个问题的解决方案在于 scipy 的稀疏矩阵。我尝试使用 coo_matrix 这将是完美的修复,但它仅在 2d 中可用,但是,如果我每天过滤掉,那么我可以将 x 和 y 坐标提取为稀疏矩阵,然后我将循环减少到天数。这是我的实现(也许很天真):

days = {}
for i in range(0, days + 1):
    x = df.loc[df['day'] == i, 'x'].values
    y = df.loc[df['day'] == i, 'y'].values
    v = df.loc[df['day'] == i, 'value'].values
    out = coo_matrix((v, (x,y)), shape=(3, 3)).toarray()
    days[f'days {i}'] = out

使用 pythons 计时器模块,最后一段代码运行了大约 0.6 秒,有 40k 个数据点,并与

for row in df.iterrows():
    x = 2

这花了大约 7 秒。这是我目前能做的最好的事情,以避免数据点的完整循环。

ps:用numpy也可以达到同样的效果。

days = {}
for i in range(0, days + 1):
    x = df.loc[df['day'] == i, 'x'].values
    y = df.loc[df['day'] == i, 'y'].values
    v = df.loc[df['day'] == i, 'value'].values
    out = np.zeros(3, 3)
    out[x, y] = v
    days[f'days {i}'] = out.tolist()

推荐阅读