python - Pandas :插入缺失的行并在数据框中绘制多个系列

标签 python pandas matplotlib time-series

我正在寻找指向适当文档的指针,以便在 pylab 中使用 pandas 完成下面描述的分析任务。我以前编写过 python + matplotlib 函数来完成大部分工作,但生成的代码速度慢且维护起来麻烦。 pandas 似乎具有所需的功能,但我在寻找正确的方法和功能时陷入困境。

In [1]: import pandas as pd

In [6]: df = pd.read_csv("tinyexample.csv", parse_dates=2)

In [7]: df
Out[7]: 
   I                  t       A      B        C     D        E
0  1  08/06/13 02:34 PM  109.40  105.50  124.30  1.00  1930.95
1  1  08/06/13 02:35 PM  110.61  106.21  124.30  0.90  1964.89
2  1  08/06/13 02:37 PM  114.35  108.84  124.30  0.98  2654.33
3  1  08/06/13 02:38 PM  115.38  109.81  124.30  1.01  2780.63
4  1  08/06/13 02:40 PM  116.08  110.94  124.30  0.99  2521.28
5  4  08/06/13 02:34 PM  105.03  100.96  127.43  1.12  2254.51
6  4  08/06/13 02:35 PM  106.73  101.72  127.43  1.08  2661.76
7  4  08/06/13 02:38 PM  111.21  105.17  127.38  1.06  3163.07
8  4  08/06/13 02:40 PM  111.69  106.28  127.38  1.09  2898.73

以上是来自 radio 连接数据记录器网络的每分钟读数的一小部分。该示例显示 2 个记录器在 10 分钟内的输出。这 数十个记录器在多日内输出了实际数据文件。

“I”列是记录器 ID,“t”是时间戳,“A-C”是温度,“D”是流速,“E”是根据 A、B 和 D 计算的能量率。

由于 radio 连接不佳,所有记录器在随机时间都缺少读数

具体来说,我想做如下的事情

for i in I:
    ## Insert rows for all missing timestamps with interpolated values for A through E
    ## Update a new column 'F' with a cumulative sum of 'E' (actually E/60)

然后我希望能够定义一个绘图函数,允许我输出垂直对齐的条形图 类似于 http://pandas.pydata.org/pandas-docs/dev/visualization.html 的文档中显示的内容.我试过了

df.plot(subplots=True, sharex=True)

这几乎可以满足我的需要,除了

  1. 它按索引编号而不是按日期绘制。
  2. 它不会为每个记录器 ID 创建单独的绘图线。

plot results

最后,我希望能够选择要绘制的记录器 ID 和数据列的子集,例如

def myplot(df, ilist, clist):
    """
    ilist is of the form [ n, m, p, ...] where n, m, and p are logger id's in column 'I'
    clist is a list of column labels.

    Produces stack of strip chart plots, one for each column contain plot lines for each id.
    """ 

解决方案(使用 Dan Allan 接受的答案——谢谢 Dan)

import pandas as pd
import matplotlib.pyplot as plt 

def myinterpolator(grp, cols = ['I', 'A', 'B', 'C', 'D', 'E']):
    index = pd.date_range(freq='1min', 
            start=grp.first_valid_index(), 
            end=grp.last_valid_index())
    g1  = grp.reindex(set(grp.index).union(index)).sort_index()
    for col in cols:
        g1[col] = g1[col].interpolate('time').ix[index]
    g1['F'] = g1['E'].cumsum()    
    return g1 


def myplot(df, ilist, clist):
    df1 = df[df['I'].isin(ilist)][clist + ['I']]
    fig, ax = plt.subplots(len(clist))
    for I, grp in df1.groupby('I'):
        for j, col in enumerate(clist):
            grp[col].plot(ax=ax[j], sharex=True)


df = pd.read_csv("tinyexample.csv", parse_dates=True, index_col=1)

df_interpolated = pd.concat([myinterpolator(grp) for I, grp in df.groupby('I')])
myplot(df_interpolated, ilist=[1,4], clist=['F', 'A', 'C'])
plt.tight_layout()   

最佳答案

其中有两点很棘手:插值(请参阅 Tom 的评论)和您希望在同一子图中绘制不同的传感器。 subplots=True 关键字不足以实现这一微妙之处;你必须使用循环。这行得通。

import matplotlib.pyplot as plt

def myplot(df, ilist, clist):
    df1 = df[df['I'].isin(ilist)][clist + ['t', 'I']].set_index('t')
    fig, ax = plt.subplots(len(clist))
    for I, grp in df1.groupby('I'):
        for j, col in enumerate(clist):
            grp[col].plot(ax=ax[j], sharex=True)

用法:

df['t'] = pd.to_datetime(df['t']) # Make sure pandas treats t as times.
myplot(df, [1, 4], ['A', 'B', 'C'])
plt.tight_layout() # cleans up the spacing of the plots

enter image description here

您可能实际上不需要插值。即使缺少某些数据,上面的代码也会执行,并且绘图线在视觉上线性插入数据。但是如果你想要实际的插值——比如说额外的分析——请参阅 this answer .

关于python - Pandas :插入缺失的行并在数据框中绘制多个系列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18362212/

相关文章:

c++ - Ctypes 在使用 CMake 创建的共享库中找不到符号

python - 设置值多索引 Pandas

python - 如何在多索引 Pandas 数据框中选择嵌套列

python - 对 pandas groupby 中的列进行操作

python - 将每个数字数组元素绘制为一条水平线

python - 如何在 Spark (Python) 中对我的 Row 对象的字段进行排序

python - 使用 Numba 在 Python 中求解最小二乘法

python - 如何确定每行多列中分类标签的最高出现次数

matplotlib - 删除 matplotlib 图窗的状态栏

python - 如何在 matplotlib 中制作 3D 散点图