关于matplotlib:Python – 读取csv并按列分组数据

Python - reading a csv and grouping data by a column

我正在使用一个csv文件,其中有3列,如下所示:

1
2
3
4
5
6
7
8
timeStamp, value, label
15:22:57, 849, CPU pid=26298:percent
15:22:57, 461000, JMX MB
15:22:58, 28683, Disks I/O
15:22:58, 3369078, Memory pid=26298:unit=mb:resident
15:22:58, 0, JMX 31690:gc-time
15:22:58, 0, CPU pid=26298:percent
15:22:58, 503000, JMX MB

"label"列包含不同的值(总共5个),其中包括空格、冒号和其他特殊字符。

我试图实现的是用每一个度量来绘制时间(要么在同一个图上,要么在单独的图上)。我可以用matplotlib来完成这项工作,但我首先需要根据"label"对[timeStamps, value]对进行分组。

我查看了csv.DictReader以获得标签,itertools.groupby以"标签"进行分组,但我正努力以一种适当的"Python式"方式做到这一点。

有什么建议吗?

谢谢


您可以尝试熊猫,它为处理数据提供了一个很好的结构。

将csv读取到DataFrame

1
2
3
4
5
6
7
8
9
10
11
12
13
14
In [123]: import pandas as pd

In [124]: df = pd.read_csv('test.csv', skipinitialspace=True)

In [125]: df
Out[125]:
  timeStamp    value                              label
0  15:22:57      849              CPU pid=26298:percent
1  15:22:57   461000                             JMX MB
2  15:22:58    28683                          Disks I/O
3  15:22:58  3369078  Memory pid=26298:unit=mb:resident
4  15:22:58        0                  JMX 31690:gc-time
5  15:22:58        0              CPU pid=26298:percent
6  15:22:58   503000                             JMX MB

labelDataFrame分组

1
In [154]: g =  df.groupby('label')

现在你可以得到你想要的了

1
2
3
4
5
In [155]: g.get_group('JMX MB')
Out[155]:
  timeStamp   value   label
1  15:22:57  461000  JMX MB
6  15:22:58  503000  JMX MB


你不需要groupby;你想用collections.defaultdict收集一系列由标签键控的[timestamp, value]对:

1
2
3
4
5
6
7
8
9
10
11
from collections import defaultdict
import csv

per_label = defaultdict(list)

with open(inputfilename, 'rb') as inputfile:
    reader = csv.reader(inputfile)
    next(reader, None)  # skip the header row

    for timestamp, value, label in reader:
        per_label[label.strip()].append([timestamp.strip(), float(value)])

现在,per_label是一个以标签为键的字典,一个以[timestamp, value]对为值的列表;我去掉了空白(您的输入样本有很多额外的空白),并将value列转换为浮点。

对于(有限的)输入样本,结果是:

1
2
3
4
5
{'CPU pid=26298:percent': [['15:22:57', 849.0], ['15:22:58', 0.0]],
 'Disks I/O': [['15:22:58', 28683.0]],
 'JMX 31690:gc-time': [['15:22:58', 0.0]],
 'JMX MB': [['15:22:57', 461000.0], ['15:22:58', 503000.0]],
 'Memory pid=26298:unit=mb:resident': [['15:22:58', 3369078.0]]}


您可以使用numpy.loadtxt

1
2
3
4
import numpy as np
result = np.loadtxt('MYFILE', usecols=(0, 1, 2),
          dtype=[('time', 'S8'), ('values', np.uint), ('label', 'S33')],
          delimiter=', ')

这将把您的表加载到一个结构化数组中,其中时间保存为8个字符的字符串("s8"),值保存为无符号整数,标签保存为最多33个字符的字符串("s33"),您可能需要调整此大小)。然后可以按以下类型为值编制索引:

1
2
>>> print result['values']
[    849  461000   28683 3369078       0       0  503000]

并根据标签过滤,如果需要:

1
2
>>> print result['values'][result['label'] == 'JMX MB']
[461000 503000]

要将时间从字符串转换为浮点数,可以使用pylab的日期datestr2num并将其作为loadtxt的转换器提供:

1
2
3
4
import pylab
result = np.loadtxt('MYFILE', usecols=(0, 1, 2),
           dtype=[('time', np.float), ('values', np.uint), ('label', 'S33')],
           delimiter=', ', converters={0: pylab.datestr2num})