pandas 避免在折线图上绘制缺失值

7rtdyuoh  于 2023-04-28  发布在  其他
关注(0)|答案(4)|浏览(252)

我想要一个线图来指示是否有一段数据丢失,例如:

然而,下面的代码填充了缺失的数据,创建了一个可能误导的图表:

import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt

# load csv
df=pd.read_csv('data.csv')
# plot a graph
g = sns.lineplot(x="Date", y="Data", data=df)
plt.show()

我应该在我的代码中做些什么来避免填充缺失的值?
csv如下:

Date,Stagnation
01-07-03,
01-08-03,
01-09-03,
01-10-03,
01-11-03,
01-12-03,100
01-01-04,
01-02-04,
01-03-04,
01-04-04,
01-05-04,39
01-06-04,
01-07-04,
01-08-04,53
01-09-04,
01-10-04,
01-11-04,
01-12-04,
01-01-05,28
01-02-05,
01-03-05,
01-04-05,
01-05-05,
01-06-05,25
01-07-05,50
01-08-05,21
01-09-05,
01-10-05,
01-11-05,17
01-12-05,
01-01-06,16
01-02-06,14
01-03-06,21
01-04-06,
01-05-06,14
01-06-06,14
01-07-06,
01-08-06,
01-09-06,10
01-10-06,13
01-11-06,8
01-12-06,20
01-01-07,8
01-02-07,20
01-03-07,10
01-04-07,9
01-05-07,19
01-06-07,6
01-07-07,
01-08-07,11
01-09-07,17
01-10-07,12
01-11-07,13
01-12-07,17
01-01-08,11
01-02-08,8
01-03-08,9
01-04-08,21
01-05-08,8
01-06-08,8
01-07-08,14
01-08-08,14
01-09-08,19
01-10-08,27
01-11-08,7
01-12-08,16
01-01-09,25
01-02-09,17
01-03-09,9
01-04-09,14
01-05-09,14
01-06-09,3
01-07-09,14
01-08-09,5
01-09-09,8
01-10-09,13
01-11-09,10
01-12-09,10
01-01-10,8
01-02-10,12
01-03-10,12
01-04-10,15
01-05-10,13
01-06-10,5
01-07-10,6
01-08-10,7
01-09-10,13
01-10-10,19
01-11-10,19
01-12-10,13
01-01-11,11
01-02-11,11
01-03-11,15
01-04-11,9
01-05-11,14
01-06-11,7
01-07-11,9
01-08-11,11
01-09-11,24
01-10-11,14
01-11-11,17
01-12-11,14
01-01-12,10
01-02-12,13
01-03-12,12
01-04-12,12
01-05-12,12
01-06-12,9
01-07-12,7
01-08-12,9
01-09-12,15
01-10-12,13
01-11-12,25
01-12-12,13
01-01-13,13
01-02-13,15
01-03-13,23
01-04-13,22
01-05-13,14
01-06-13,13
01-07-13,20
01-08-13,17
01-09-13,27
01-10-13,15
01-11-13,16
01-12-13,18
01-01-14,18
01-02-14,19
01-03-14,14
01-04-14,14
01-05-14,10
01-06-14,11
01-07-14,8
01-08-14,18
01-09-14,16
01-10-14,26
01-11-14,35
01-12-14,15
01-01-15,14
01-02-15,16
01-03-15,13
01-04-15,12
01-05-15,12
01-06-15,9
01-07-15,10
01-08-15,11
01-09-15,11
01-10-15,13
01-11-15,13
01-12-15,10
01-01-16,12
01-02-16,12
01-03-16,13
01-04-16,13
01-05-16,12
01-06-16,7
01-07-16,6
01-08-16,13
01-09-16,15
01-10-16,13
01-11-16,12
01-12-16,14
01-01-17,11
01-02-17,11
01-03-17,10
01-04-17,11
01-05-17,7
01-06-17,8
01-07-17,10
01-08-17,12
01-09-17,13
01-10-17,14
01-11-17,15
01-12-17,13
01-01-18,13
01-02-18,16
01-03-18,12
01-04-18,14
01-05-18,12
01-06-18,8
01-07-18,8
dohp0rv5

dohp0rv51#

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns

# Make example data
s = """2018-01-01
2018-01-02,100
2018-01-03,105
2018-01-04
2018-01-05,95
2018-01-06,90
2018-01-07,80
2018-01-08
2018-01-09"""
df = pd.DataFrame([row.split(",") for row in s.split("\n")], columns=["Date", "Data"])
df = df.replace("", np.nan)
df["Date"] = pd.to_datetime(df["Date"])
df["Data"] = df["Data"].astype(float)

三种选择:
1)使用pandasmatplotlib
2)如果您需要seaborn:不是它的用途,但对于像你这样的常规日期,你可以使用pointplot开箱即用。

fig, ax = plt.subplots(figsize=(10, 5))

plot = sns.pointplot(
    ax=ax,
    data=df, x="Date", y="Data"
)

ax.set_xticklabels([])

plt.show()

3)如果您需要seabornlineplot:我看了一下源代码,它看起来像lineplot在绘图之前从DataFrame中删除nans。所以不幸的是,它不可能正确地做到这一点。你可以使用一些先进的黑客技术,并使用hue参数将单独的部分放在单独的bucket中。我们使用nans的出现来编号部分。

fig, ax = plt.subplots(figsize=(10, 5))

plot = sns.lineplot(
    ax=ax,
    data=df, x="Date", y="Data",
    hue=df["Data"].isna().cumsum(), palette=["black"]*sum(df["Data"].isna()), legend=False, markers=True
)
ax.set_xticklabels([])

plt.show()

不幸的是,标记参数目前似乎被破坏了,所以如果你想看到两边都有nans的日期,你需要修复它。

wqsoz72f

wqsoz72f2#

尝试将NaN值设置为np.inf-- Seaborn不会绘制这些点,也不会将之前的点与之后的点连接起来。

lp0sw83n

lp0sw83n3#

根据Denziloe的回答:
有三种选择:
1)使用pandasmatplotlib
2)如果您需要seaborn:不是它的用途,而是像pointplot这样的常规日期可以开箱即用。

fig, ax = plt.subplots(figsize=(10, 5))

plot = sns.pointplot(
    ax=ax,
    data=df, x="Date", y="Data"
)

ax.set_xticklabels([])

plt.show()

基于问题数据构建的图表如下所示:

优点:

  • 易于实施
  • 数据中被None包围的离群值将在图上很容易注意到

缺点:

  • 生成这样的图需要很长时间(与lineplot相比)
  • 当有许多点时,就很难阅读这样的图表

3)如果您需要seabornlineplothue参数可用于将单独的节放入单独的桶中。我们使用nan的出现次数对节进行编号。

fig, ax = plt.subplots(figsize=(10, 5))

plot = sns.lineplot(
    ax=ax
    , data=df, x="Date", y="Data"
    , hue=df["Data"].isna().cumsum()
    , palette=["blue"]*sum(df["Data"].isna())
    , legend=False, markers=True
)

ax.set_xticklabels([])

plt.show()

优点:

  • 线图
  • 易读
  • 生成速度快于点图

缺点:

  • 数据中被None包围的离群值将不会绘制在图表上

该图如下所示:

7jmck4yq

7jmck4yq4#

  • 由于数据已经在pandas.DataFrame中,最简单的解决方案是直接使用pandas.DataFrame.plot绘图,它使用matplotlib作为默认绘图后端。
  • 顺便说一下,seabornmatplotlib的高级API。
    *python 3.11.2pandas 2.0.0matplotlib 3.7.1中测试
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# load the csv file
df = pd.read_csv('d:/data/hh.ru_stack.csv')

# convert the date column to a datetime.date
df.Date = pd.to_datetime(df.Date, format='%d-%m-%y').dt.date

# plot with markers
ax = df.plot(x='Date', marker='.', figsize=(9, 6))

# set the ticks for every year if desired
ax.xaxis.set_major_locator(mdates.YearLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y"))

fig, ax = plt.subplots(figsize=(9, 6))
ax.plot('Date', 'Stagnation', '.-', data=df)
ax.legend()

ax.xaxis.set_major_locator(mdates.YearLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y"))

相关问题