使用 seaborn 绘制时间序列数据
Posted
技术标签:
【中文标题】使用 seaborn 绘制时间序列数据【英文标题】:Plotting time-series data with seaborn 【发布时间】:2014-05-12 18:51:23 【问题描述】:假设我使用以下代码创建了一个完全随机的Dataframe
:
from pandas.util import testing
from random import randrange
def random_date(start, end):
delta = end - start
int_delta = (delta.days * 24 * 60 * 60) + delta.seconds
random_second = randrange(int_delta)
return start + timedelta(seconds=random_second)
def rand_dataframe():
df = testing.makeDataFrame()
df['date'] = [random_date(datetime.date(2014,3,18),datetime.date(2014,4,1)) for x in xrange(df.shape[0])]
df.sort(columns=['date'], inplace=True)
return df
df = rand_dataframe()
这导致了本文底部显示的数据框。我想使用seaborn
中的timeseries 可视化功能来绘制我的列A
、B
、C
和D
,以便我得到以下方面的信息:
我该如何解决这个问题?从我在this notebook 上看到的内容来看,电话应该是:
sns.tsplot(df, time="time", unit="unit", condition="condition", value="value")
但这似乎要求数据框以不同的方式表示,列以某种方式编码time
、unit
、condition
和value
,这不是我的情况。如何将我的数据框(如下所示)转换为这种格式?
这是我的数据框:
date A B C D
2014-03-18 1.223777 0.356887 1.201624 1.968612
2014-03-18 0.160730 1.888415 0.306334 0.203939
2014-03-18 -0.203101 -0.161298 2.426540 0.056791
2014-03-18 -1.350102 0.990093 0.495406 0.036215
2014-03-18 -1.862960 2.673009 -0.545336 -0.925385
2014-03-19 0.238281 0.468102 -0.150869 0.955069
2014-03-20 1.575317 0.811892 0.198165 1.117805
2014-03-20 0.822698 -0.398840 -1.277511 0.811691
2014-03-20 2.143201 -0.827853 -0.989221 1.088297
2014-03-20 0.299331 1.144311 -0.387854 0.209612
2014-03-20 1.284111 -0.470287 -0.172949 -0.792020
2014-03-22 1.031994 1.059394 0.037627 0.101246
2014-03-22 0.889149 0.724618 0.459405 1.023127
2014-03-23 -1.136320 -0.396265 -1.833737 1.478656
2014-03-23 -0.740400 -0.644395 -1.221330 0.321805
2014-03-23 -0.443021 -0.172013 0.020392 -2.368532
2014-03-23 1.063545 0.039607 1.673722 1.707222
2014-03-24 0.865192 -0.036810 -1.162648 0.947431
2014-03-24 -1.671451 0.979238 -0.701093 -1.204192
2014-03-26 -1.903534 -1.550349 0.267547 -0.585541
2014-03-27 2.515671 -0.271228 -1.993744 -0.671797
2014-03-27 1.728133 -0.423410 -0.620908 1.430503
2014-03-28 -1.446037 -0.229452 -0.996486 0.120554
2014-03-28 -0.664443 -0.665207 0.512771 0.066071
2014-03-29 -1.093379 -0.936449 -0.930999 0.389743
2014-03-29 1.205712 -0.356070 -0.595944 0.702238
2014-03-29 -1.069506 0.358093 1.217409 -2.286798
2014-03-29 2.441311 1.391739 -0.838139 0.226026
2014-03-31 1.471447 -0.987615 0.201999 1.228070
2014-03-31 -0.050524 0.539846 0.133359 -0.833252
最后,我正在寻找的是图的叠加(每列一个),其中每个图如下所示(注意不同的 CI 值得到不同的 alpha 值):
【问题讨论】:
您的索引中有重复的日期。故意的?如果有,那有什么意义? 谢谢@PaulH 这是故意的,尽管它们可以移动到列中。我每个日期有多个样本,我想在图中的条带厚度中捕捉每个日期的可变性。 为了冗长,这条线本身来自给定日期的平均值,阴影带以最小值和最大值为界? 另外,你能添加你的导入语句吗?randrange
来自哪里?
@PaulH 我修复了导入。理想情况下,乐队应该在Q1
和Q3
处捕获置信区间,如en.wikipedia.org/wiki/File:Boxplot_vs_PDF.svg
【参考方案1】:
我认为tsplot
不会处理您拥有的数据。它对输入数据所做的假设是您在每个时间点采样了相同的单位(尽管您可能会丢失某些单位的时间点)。
例如,假设您连续一个月每天测量同一个人的血压,然后您想按条件绘制平均血压(其中“条件”变量可能是他们的饮食)。 tsplot
可以做到这一点,调用类似于sns.tsplot(df, time="day", unit="person", condition="diet", value="blood_pressure")
这种情况不同于让一大群人吃不同的饮食,然后每天从每组中随机抽取一些人并测量他们的血压。从您提供的示例中,您的数据似乎是这样的结构。
但是,想出一个 matplotlib 和 pandas 的组合来做我认为你想要的事情并不难:
# Read in the data from the *** question
df = pd.read_clipboard().iloc[1:]
# Convert it to "long-form" or "tidy" representation
df = pd.melt(df, id_vars=["date"], var_name="condition")
# Plot the average value by condition and date
ax = df.groupby(["condition", "date"]).mean().unstack("condition").plot()
# Get a reference to the x-points corresponding to the dates and the the colors
x = np.arange(len(df.date.unique()))
palette = sns.color_palette()
# Calculate the 25th and 75th percentiles of the data
# and plot a translucent band between them
for cond, cond_df in df.groupby("condition"):
low = cond_df.groupby("date").value.apply(np.percentile, 25)
high = cond_df.groupby("date").value.apply(np.percentile, 75)
ax.fill_between(x, low, high, alpha=.2, color=palette.pop(0))
这段代码产生:
【讨论】:
谢谢。为什么你认为tsplot
行不通?我可以理解统计假设不会延续,但tsplot
怎么知道样本来自哪里?它是否假设每个日期的元素数量恒定?
这就是unit
参数的用途——你告诉它每个样本对应哪个单位,然后它期望每个时间点代表每个单位。
我问的原因是因为我对tsplot
对置信区间的不同值使用不同的 alpha 值的能力特别感兴趣(我更新了 OP 以在最后突出显示这一点)
您可以添加一个内部循环并在不同的时间间隔内重复 fill_between
块 tsplot
只是在彼此之上绘制多个补丁,而不是 alpha 本身的任何花哨的东西。
是否可以避免将数据转换为“长格式”(效率不高)??以上是关于使用 seaborn 绘制时间序列数据的主要内容,如果未能解决你的问题,请参考以下文章