2016-07-09 14 views
1

シミュレーションの結果、CSVファイルは空白で分割されています。 ABCDを入力し、ノード1の、すなわち平均値、Iは、ノードの数とタイプによってファイルをフィルタリングする必要がメトリックを使用する異なるデータ型を持つ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の平均、タイプEfgh;

私はNumpyが配列を扱うのに非常に便利だと知っていますが、1つのデータ型しか受け付けません。私の現在のコードは次のようになります(今のところファイルの内容を表示しています)。

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

はおそらく代わりにnumpyののpandasを使用します。

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

を、以下の結果を得:あなたはタブ区切りのファイルを持っていると仮定すると、コードは次のように簡単になります私の試みはitertoolsを使用して

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

。基本的には、groupbyメソッドを利用して、ラムダ関数で連続したデータをグループ化することができます。 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

私は、ファイルにあなたのサンプルを入れた場合、私はあなたがそれが2列名として解釈するMetric 1のような名前を持っているので、私はnames=Trueを使用することができなかった

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のリストと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')]) 

Iは、任意のmeanを取ることができますこのRecoのサブセットからの数値フィールドの数RDS:私も変数にこれらのフィールドを割り当て、それらの直接

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つのフロートフィールドで働くことができる

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

、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]]) 

metricsnodesは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は、パンダとitertoolsがありますが、きちんとしたgroupby機能を持っていません。

+0

これは私にとって完璧に機能しました。ご協力いただきありがとうございます – Thiago

関連する問題