数据帧按列数切片并绘制热图

Dataframe slice by count of columns and draw heatmap

提问人:mangosrk 提问时间:4/10/2023 更新时间:4/10/2023 访问量:47

问:

我有一个数据帧。我根据每个内核模块收集了延迟数据。每个模块的时间数据不同3000~1000。我想对数据进行切片,使每个模块的时间大小相等,特别是从 0 到 1000。 下面是我的原始数据帧

time, module_name, latency
0, module1, 268
1, module1, 300
...
999, module1, 300
0, module2, 234
1, module2, 345
...
3000, module2, 345

我对我的数据进行了切片,使其均匀大小为 1000,使用每个模块的 iloc 函数。

trace1000 = df1.groupby('module_name').apply(lambda x: x.iloc[0:999]

结果,我得到了下面的数据帧。 正如我所料,我得到了均匀大小的跟踪,每个模块 1000 个。

module_name, , module_name, latency
module1, 2000, module1, 268
module1, 2001, module1, 300
...
module2, 9085, module1, 234
module2, 9086, module1, 345
...

但是,我不知道为什么我得到重复的列名“module_name”和奇怪的第二列没有名称。 我试图通过这个删除或仅选择列,但失败了。

heat_df = trace1000[["module_name","latency"]]

我的目标是绘制一个 seaborn 热图(x 轴:时间(范围 1-1000),y 轴:module_name(模块数:30,热量:延迟(范围:100~900)。我期待如下图所示的图表

enter image description here

Python DataFrame Seaborn 切片 热图

评论


答:

0赞 Oliver Lopez 4/10/2023 #1

假设我们生成一个较小的示例,由列 、 和 组成。考虑从 0-4 开始,从“module_0”到“module_9”,延迟是一个随机变量。timemodule_namelatencytimemodule_name

import pandas as pd
import numpy as np

df1 = pd.DataFrame(
    {
    "time": np.tile(np.arange(0,5),10),
    "module_n": np.array([[i]*5 for i in np.arange(10)]).flatten(),
    }
).assign(
    module_name=lambda x: "module_" + x.module_n.astype(str),
    latency=np.random.random(50)
).drop(columns="module_n")
df1

下面是输出的预览:

    time module_name   latency
0      0    module_0  0.650732
1      1    module_0  0.184202
2      2    module_0  0.741331
3      3    module_0  0.903374
4      4    module_0  0.440044
..   ...         ...       ...
45     0    module_9  0.024248
46     1    module_9  0.468306
47     2    module_9  0.763958
48     3    module_9  0.556926
49     4    module_9  0.696217

[50 rows x 3 columns]

现在,您要应用一个操作,该操作将获取按列中的值分组的每个子集并执行操作。.groupbydf1module_name

让我们看一下这些子集之一:

df1_group_module_0 = df1.loc[df1.module_name=="module_0"]
df1_group_module_0
   time module_name   latency
0     0    module_0  0.650732
1     1    module_0  0.184202
2     2    module_0  0.741331
3     3    module_0  0.903374
4     4    module_0  0.440044

您指定要与 一起应用的操作是 。对于这个较小的示例,假设我只想获取前两个值,因此我将使用 。让我们看看当我们将此操作应用于一个组(我们上面选择的组)时会发生什么:.groupbylambda x: x.iloc[0:999]x.iloc[0:2]

df1_group_module_1.iloc[0:2]
   time module_name   latency
0     0    module_0  0.650732
1     1    module_0  0.184202

你得到的是一个包含列 、 和 的新数据帧,它对应于 的前两行。timemodule_namelatencymodule_0

将合并对每个组应用上述操作的结果,返回结果并在结果前面加上“module_name”列。这就是为什么你会得到一个额外的列,以及一个额外的列,其中包含组合结果的索引(你可以使用 ..groupby.apply(lambda x: x.iloc[0:2])module_name.reset_index(drop=True)

看起来您在这里尝试做的是一个更简单的操作,不需要 groupby:

tr2 = df1.loc[df1.time<=1]  # in your case time<=999 
    time module_name   latency
0      0    module_0  0.650732
1      1    module_0  0.184202
5      0    module_1  0.122834
6      1    module_1  0.843534
10     0    module_2  0.108903
..   ...         ...       ...
36     1    module_7  0.720628
40     0    module_8  0.694778
41     1    module_8  0.649239
45     0    module_9  0.024248
46     1    module_9  0.468306

[20 rows x 3 columns]

另一个只接受前 N 个观测值的选项是使用 .head(N),如以下答案所示 https://stackoverflow.com/a/20069379/3828592