2016-07-09 70 views
1

作爲仿真的結果,我有一堆用空格分隔的csv文件。看下面的例子:具有不同數據類型的Python片/子集陣列

Time Node Type Metric 1 Metric 2 
0.00 1 Abcd 1234.5678 9012.3456 
0.00 1 Efgh 1234.5678 9012.3456 
0.01 2 Abcd 1234.5678 9012.3456 
0.01 2 Efgh 1234.5678 9012.3456 
0.02 3 Abcd 1234.5678 9012.3456 
0.02 3 Efgh 1234.5678 9012.3456 
0.03 1 Abcd 1234.5678 9012.3456 
0.03 1 Efgh 1234.5678 9012.3456 
0.04 2 Abcd 1234.5678 9012.3456 
0.04 2 Efgh 1234.5678 9012.3456 
... 

要使用指標,我需要按節點編號和類型,即節點1的平均值過濾文件,鍵入Abcd;節點1的均值,輸入Efgh;等

我知道Numpy處理數組非常有用,但它只接受一種數據類型。我當前的代碼看起來是這樣的(這只是打印文件的內容現在):

import sys 

filename = sys.argv[1] 
# read file 
with open(filename, 'r') as f: 
    for line in f: 
     print line 

# TO DO 
# Slice file into different 'Node' number 

# Slice subfile into different 'Type' 

# Calculate metrics (mean, max, min, and others) 
# which is fine once I have the sliced arrays 

# Plot graphs 

有誰知道如何以有效的方式做到這一點? PS:我正在使用Python 2.7。

感謝

回答

2

你可能想使用pandas,而不是numpy的。假設你有一個製表符分隔的文件,代碼將是如此簡單:

import pandas as pd 
data = pd.read_csv("abc.csv", delimiter="\t") 
result = data.groupby("Node").mean() 

和產量得到以下結果:

Time Metric 1 Metric 2 
Node    
1 0.015 1234.5678 9012.3456 
2 0.025 1234.5678 9012.3456 
3 0.020 1234.5678 9012.3456 
+0

@ThiagoTeixeira不客氣。是的,熊貓會做到這一點,如果你像這樣分組成多列:'data.groupby([「Node」,「Type」])。mean()' –

+0

我會嘗試。謝謝! – Thiago

0

我嘗試使用itertools。基本上,這利用了groupby方法,它允許您通過lambda函數將連續的數據組合在一起。如果在使用groupby之前對數據集進行排序,那麼您可以通過任意鍵對數據集進行分組。

不知道你的數據集有多大,但如果它不是太大,這應該做的伎倆。

from itertools import groupby 
import sys 

filename = sys.argv[1] 

def parse_data(line): 
    # converts a single entry in the csv to a list of values 
    return [ 
      val for val in line.split(' ') if val != '' 
    ] 


with open(filename, 'r') as input: 
    keys = input.readline().split() 

    dataset = [ 
     parse_data(line) 
     for line in input.readlines() 
    ] 

    # group dataset by node 
    dataset_grouped_by_node = groupby(
     sorted(dataset, key=lambda x: x[1]), lambda x: x[1] 
    ) 

    for node, node_group in dataset_grouped_by_node: 
     # group each of those subgroups by type 
     group_sorted_by_type = groupby(
      sorted(node_group, key=lambda x: x[2]), lambda x: x[2] 
     ) 

     for type, type_group in group_sorted_by_type: 
      print type, node 

      for item in type_group: 
       print item 

       # calculate statistics on these subgroups 

你可以清理一下,以便廣義的「分組」功能,如果你想要的,但我認爲這應該得到你所需要的。

1

如果我把你的樣品中的文件,我可以將它與

In [45]: names=['Time','Node','Type','Metric_1','Metric_2'] 
In [46]: data = np.genfromtxt('stack38285208.txt', dtype=None, names=names, skip_header=1) 
In [47]: data 
Out[47]: 
array([(0.0, 1, b'Abcd', 1234.5678, 9012.3456), 
     (0.0, 1, b'Efgh', 1234.5678, 9012.3456), 
     (0.01, 2, b'Abcd', 1234.5678, 9012.3456), 
     (0.01, 2, b'Efgh', 1234.5678, 9012.3456), 
     (0.02, 3, b'Abcd', 1234.5678, 9012.3456), 
     (0.02, 3, b'Efgh', 1234.5678, 9012.3456), 
     (0.03, 1, b'Abcd', 1234.5678, 9012.3456), 
     (0.03, 1, b'Efgh', 1234.5678, 9012.3456), 
     (0.04, 2, b'Abcd', 1234.5678, 9012.3456), 
     (0.04, 2, b'Efgh', 1234.5678, 9012.3456)], 
     dtype=[('Time', '<f8'), ('Node', '<i4'), ('Type', 'S4'), ('Metric_1', '<f8'), ('Metric_2', '<f8')]) 

加載到一個結構化的numpy陣列我不能使用names=True,因爲你有一個像Metric 1的名字,它會解釋爲2個名。因此,單獨的names列表和skip_header。我使用的是Python3,所以S4格式的字符串顯示爲b'Efgh'

我可以通過字段名稱訪問字段(列),並且可以對這些字段進行各種過濾和數學運算。例如:

字段其中Typeb'Abcd'

In [63]: data['Type']==b'Abcd' 
Out[63]: array([ True, False, True, False, True, False, True, False, True, False], dtype=bool) 

並且其中Node爲1:

In [64]: data['Node']==1 
Out[64]: array([ True, True, False, False, False, False, True, True, False, False], dtype=bool) 

和在一起:

In [65]: (data['Node']==1)&(data['Type']==b'Abcd') 
Out[65]: array([ True, False, False, False, False, False, True, False, False, False], dtype=bool) 
In [66]: ind=(data['Node']==1)&(data['Type']==b'Abcd') 
In [67]: data[ind] 
Out[67]: 
array([(0.0, 1, b'Abcd', 1234.5678, 9012.3456), 
     (0.03, 1, b'Abcd', 1234.5678, 9012.3456)], 
     dtype=[('Time', '<f8'), ('Node', '<i4'), ('Type', 'S4'), ('Metric_1', '<f8'), ('Metric_2', '<f8')]) 

我可以採取任何mean來自這個子集的數字字段RDS:

In [68]: data[ind]['Metric_1'].mean() 
Out[68]: 1234.5678 
In [69]: data[ind]['Metric_2'].mean() 
Out[69]: 9012.3456000000006 

我也可以分配這些字段變量以及與這些直接

In [70]: nodes=data['Node'] 
In [71]: types=data['Type'] 
In [72]: nodes 
Out[72]: array([1, 1, 2, 2, 3, 3, 1, 1, 2, 2]) 
In [73]: types 
Out[73]: 
array([b'Abcd', b'Efgh', b'Abcd', b'Efgh', b'Abcd', b'Efgh', b'Abcd', 
     b'Efgh', b'Abcd', b'Efgh'], 
     dtype='|S4') 

2個浮點字段工作,看作是一個2列陣列:

In [78]: metrics = data[['Metric_1','Metric_2']].view(('float',(2))) 
In [79]: metrics 
Out[79]: 
array([[ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456]]) 

metrics其中nodes是1

In [83]: metrics[nodes==1,:] 
Out[83]: 
array([[ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456], 
     [ 1234.5678, 9012.3456]]) 
In [84]: metrics[nodes==1,:].mean(axis=0) # column mean 
Out[84]: array([ 1234.5678, 9012.3456]) 

numpy沒有一個整潔的groupby功能,雖然熊貓和itertools做。

+0

這對我來說非常合適。謝謝你的幫助 – Thiago

相關問題