2013-04-25 86 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