2013-04-25 87 views
1

我与3列的csv文件的工作分组数据是这样的:Python的 - 看起来读取CSV和列

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 

“标签”列中包含不同的值(比方说一共有5 ),其中包括空格,冒号和其他特殊字符。

我试图达到的目的是为每个指标绘制时间(无论是在同一个图表上还是在单独的图表上)。我可以用Matplotlib做到这一点,但我首先需要根据'标签'对[timeStamps, value]对进行分组。

我查看了csv.DictReader以使标签和itertools.groupby按“标签”进行分组,但我正在努力以适当的“pythonic”方式做到这一点。

有什么建议吗?

感谢

+0

什么是你期望的输出为你的榜样? – waitingkuo 2013-04-25 09:30:24

+0

那么,鉴于我的输入样本都是混合的,我可能不得不为每个[标签]分开[times]和[values]。我最初的做法是读取标签,然后读取每行并根据标签存储每个[时间,值]对。但这似乎是一种非常低效的方式,这就是为什么我想查看字典和迭代器。 – 2013-04-25 09:45:59

回答

2

你不需要groupby;你想用collections.defaultdict收集一系列[timestamp, value]双通过标签键:

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列变成了浮点数。

对于产生的(有限)输入样本:

{'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]]} 
+0

这工作就像一个魅力!谢谢 我的文件最终可能有3列以上,但我认为我可以处理这个问题。我假设我只需要在阅读器中添加: 以获取时间戳,值,标签,在阅读器中: – 2013-04-25 10:17:14

+0

@ArgyriosTzakas:您也可以在'reader'中做'行',然后使用索引'row [1]' ,'row [5]'等等''csv.DictReader()'会用一个字典代替列表,所以你可以'row ['timeStamp']'而不是'row [0]';如果切换到'reader.DictReader',则省略'next()'调用。 – 2013-04-25 10:28:20

+0

谢谢Martijn。在相关主题上,是否有一种巧妙的方式来基于密钥分割我的字典,而不必硬编码?例如,我可以这样做 l1,l2,l3 = per_label.values() 但是如果我有3个以上的键? – 2013-04-25 11:52:04

2

您可以使用numpy.loadtxt

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',您可能需要调整此大小)。然后,你可以索引你值由类型:

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

和过滤根据标签,如果你想:

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

以时代从字符串转换为浮动,您可以使用pylab的日期datestr2num并提供其作为一个转换器loadtxt

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

你可以尝试pandas要处理的数据提供了一个很好的结构。

阅读DataFrame通过label

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

CSV将DataFrame

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 

集团现在你可以得到你想要的

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 
+0

非常有趣。我会看看熊猫,因为我会做许多类似的数据操作。谢谢! – 2013-04-25 10:29:42

+0

您可以添加如何将分组的CSV文件写入文件吗?不是很微不足道:http://stackoverflow.com/q/10373660/1333493 – Nemo 2015-11-06 15:13:33