python - 箱线图和散点图 python
问题描述
我有一个时间序列数据,我想在其上构建一个叠加的散点图和箱线图。数据是这样的:
TokenUsed date
0 8 2020-01-05
1 8 2020-01-05
2 8 2020-01-05
3 8 2020-01-05
4 8 2020-01-05
... ... ...
51040 7 2020-02-23
51041 7 2020-02-23
51042 7 2020-02-23
51043 7 2020-02-23
51044 7 2020-02-23
这个时间序列可以整齐地显示为箱线图(我在 x 轴是日期时遇到了麻烦,但解决了将其转换为字符串的问题)。现在,我只想显示总和优于阈值 (>81) 的数据。代码和生成的图像如下:
fig, ax = plt.subplots(figsize = (12,6))
ax = sns.boxplot(x="date", y="TokenUsed", data=df, ax= ax, whis=[0,100])
ax.axhline(81)
plt.locator_params(axis='x', nbins=10)
plt.show()
当我添加散点图时,我得到图像 (2),通过仅过滤 >81 的图像,我得到图像 (3)。我不明白的是为什么它似乎无法匹配两个图之间的 x 轴!
代码:
fig, ax = plt.subplots(figsize = (12,6))
ax = sns.boxplot(x="date", y="TokenUsed", data=df, ax= ax, whis=[0,100])
# Without filter
ax = sns.scatterplot(x="date", y="TokenUsed", data=df, ax= ax,color=".25")
# Filter
ax = sns.scatterplot(x="date", y="TokenUsed", data=df[df["TokenUsed"]>81], ax= ax,color=".25")
ax.axhline(81)
plt.locator_params(axis='x', nbins=10)
plt.show()
解决方案
回答:
df
尝试编辑您的过滤器,以便实际上没有删除任何行。也就是说,专门在TokenUsed
列上应用掩码,以便将值替换为NaN
(而不是删除整行)。以下是我将如何实现它:
#make a new copy df, use that to plot
df2['TokenUsed'] = df2['TokenUsed'].mask(df2['TokenUsed'] < 81)
ax = sns.scatterplot(x="date", y="TokenUsed", data=df2, ax= ax,color=".25")
解释
警告:这真的是我从自己的观察中对正在发生的事情的理解;我实际上并不知道幕后的实现
seaborn
不太了解您预期的日期。创建箱线图并将date
列用作 x 轴时,按列seaborn
中的每个唯一值对数据进行分组date
。它对这些字符串进行排序,然后为每个字符串创建一个整数位置(从 开始0
)。 然后根据这些整数值绘制 y 数据,并将 x-tick-labels 替换为相应的字符串 value。因此,在您的情况下,有 8 个唯一的日期字符串,它们被绘制在从0
到的 x 位置7
。此外,它们看起来像约会实际上并不重要。 您可以将更多字符串值添加到date
柱子; 它们相对于先前数据的位置将取决于它们的字母顺序(例如,我猜字符串'00-00-0000'
会首先出现,字符串'999'
会最后出现)。
过滤器df[df["TokenUsed"]>81]
会删除值低于 81的所有行TokenUsed
。这意味着过滤后的 DataFrame 将不会有与原始数据一样多的字符串日期值。这会在绘图时产生意想不到的结果。在您过滤的数据中,具有上述值的第一个日期81
是2020-02-09
. 因此,在scatterplot
调用中,这些值被绘制在x=0
,这令人困惑,因为 from 的值2020-01-05
被绘制在x=0
对 的调用中boxplot
。
解决方法是确保所有原始日期仍然存在于过滤后的数据中,但将过滤掉的值替换为NaN
不绘制任何内容。
这是我用来测试的示例:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
# fake data, only one date has values over 80
dr = ['01-05-2020'] * 100 + ['01-12-2020'] * 100 + ['01-19-2020'] * 100
data = list(np.random.randint(0,80,200)) + list(np.random.randint(50,150,100))
df = pd.DataFrame({'date':dr, 'TokenUsed':data})
fig, ax = plt.subplots(figsize = (12,6))
ax = sns.boxplot(x="date", y="TokenUsed", data=df, ax=ax, whis=[0,100])
df2 = df.copy()
df2['TokenUsed'] = df2['TokenUsed'].mask(df2['TokenUsed'] < 81)
# the fix
df2 = df.copy()
df2['TokenUsed'] = df2['TokenUsed'].mask(df2['TokenUsed'] < 81)
ax = sns.scatterplot(x="date", y="TokenUsed", data=df2, ax= ax,color=".25")
ax.axhline(81)
plt.locator_params(axis='x', nbins=10)
plt.show()
如果我使用您应用的相同过滤器,我会遇到同样的问题。
推荐阅读
- python - 将numpy数组转换为数据框
- python - Python 异步 grpc 客户端流句柄
- javascript - 如何禁用其他选项并在多个下拉列表中附加值与角度js中的相同值?
- python - 如何处理GitHub中的SQL数据库
- javascript - 旧应用程序:Angular v1.7 和 Bootstrap 3 - 缺少导航栏项
- vue.js - 如何使用 Feathers.js 对用户进行身份验证
- ffmpeg - ffmpeg 在图像上覆盖视频并删除视频黑色背景
- swiftui - 如何自定义 SwiftUI .onDrag 自动添加的手势识别器?
- r - 将自定义列添加到回归表(tab_model、sjplot)?
- sql - 代替 ”?” 在 bigquery 表中带有“Ñ”