2016-04-30 6 views
2

私は、次の構造化された配列があります。私は、各idの最大vonmisesを取得しようとしていますソート値

import numpy as np 

x = np.rec.array([(22,2,200.,2000.), (44,2,400.,4000.), (55,5,500.,5000.), (33,3,400.,3000.)], 
       dtype={'names':['subcase','id', 'vonmises','maxprincipal'], 'formats':['i4','i4','f4','f4']}) 

を。

例えば、id2のmax vonmisesは400になります。そして、対応するサブケースとmaxprincipalが必要です。ここで

は私がこれまでにやっていることである。ここでは

print repr(x[['subcase','id','vonmises']][(x['id']==2) & (x['vonmises']==max(x['vonmises'][x['id']==2]))]) 

が出力されます。

array([(44, 2, 400.0)], 
    dtype=(numpy.record, [('subcase', '<i4'), ('id', '<i4'), ('vonmises', '<f4')])) 

私は今が午前問題は、私はこれがあるすべてのIDのために仕事をしたいということです配列内では、id = 2だけではありません。

array([(44, 2, 400.0),(55, 5, 500.0),(33, 3, 400.0)], 
    dtype=(numpy.record, [('subcase', '<i4'), ('id', '<i4'), ('vonmises', '<f4')])) 

は、個々のIDを指定せずにこれを実現するための良い方法はあります:

すなわち、次の出力を取得したいですか?

答えて

2

私はあなたがこの形式を使用する理由を知っているが、ここでpandasとハックですありません。

import pandas as pd 

df = pd.DataFrame(x) 
df_ = df.groupby('id')['vonmises'].max().reset_index() 

In [213]: df_.merge(df, on=['id','vonmises'])[['id','vonmises','subcase']] 

Out[213]: 
array([[ 2., 400., 44.], 
     [ 3., 400., 33.], 
     [ 5., 500., 55.]], dtype=float32) 
+0

ありがとう、あなたはフォーマットを詳しく教えていただけますか?どんなフォーマットをお勧めしますか? – snowleopard

+0

あなたが解決しようとしている根本的な問題は何も分かりませんが、通常はグループごとに最大値をとり、グループの最大値をフィルタリングする操作をグループ化するために、 'dfのようなpandas' DataFrame'表現'と' df_'を使用します。 –

+0

オクラホマ、それは素晴らしいbtw、感謝を働いた! – snowleopard

2

ここitertools.groupby続いnp.sort(またはargsort)を使用したアプローチがあります。しかし、このグループ化ツールは発電機の発電機を生産します。

In [29]: x = np.rec.array([(22,2,200.,2000.), (44,2,400.,4000.), (55,5,500.,5000.), (33,3,400.,3000.)], 
       dtype={'names':['subcase','id', 'vonmises','maxprincipal'], 'formats':['i4','i4','f4','f4']}) 

In [30]: ind=x.argsort(order=['id','vonmises']) 

In [31]: ind 
Out[31]: 
rec.array([0, 1, 3, 2], 
      dtype=int32) 

In [32]: x[ind] 
Out[32]: 
rec.array([(22, 2, 200.0, 2000.0), (44, 2, 400.0, 4000.0), (33, 3, 400.0, 3000.0), 
(55, 5, 500.0, 5000.0)], 
      dtype=[('subcase', '<i4'), ('id', '<i4'), ('vonmises', '<f4'), ('maxprincipal', '<f4')]) 

In [33]: import itertools 

In [34]: [list(v) for k,v in itertools.groupby(x[ind],lambda i:i['id'])] 
Out[34]: 
[[(22, 2, 200.0, 2000.0), (44, 2, 400.0, 4000.0)], 
[(33, 3, 400.0, 3000.0)], 
[(55, 5, 500.0, 5000.0)]] 

その後、我々は、各グループの最後の(または分間最初の)レコードを取得し、その後recarrayを再構成する必要があります。 mx

In [39]: mx=[list(v)[-1] for k,v in itertools.groupby(x[ind],lambda i:i['id'])] 

In [43]: np.rec.fromrecords(mx,dtype=x.dtype) 
Out[43]: 
rec.array([(44, 2, 400.0, 4000.0), (33, 3, 400.0, 3000.0), (55, 5, 500.0, 5000.0)], 
      dtype=[('subcase', '<i4'), ('id', '<i4'), ('vonmises', '<f4'), ('maxprincipal', '<f4')]) 

要素が正しいdtypenp.recordですが、mx自体がリストです。

またはコンパクト:

# sort as desired 
x.sort(order=['id','vonmises']) 

# keep the first element, and every element with a different id to the one before it 
keep = np.empty(x.shape, dtype=np.bool) 
keep[0] = True 
keep[1:] = x[:-1].id != x[1:].id 

x_filt = x[keep] 

できます:ここで

g=itertools.groupby(np.sort(x,order=['id','vonmises']), lambda i:i['id']) 
np.rec.fromrecords([list(v)[-1] for k,v in g], dtype=x.dtype) 
1

はGROUPBYのないアプローチだ

rec.array([(22, 2, 200.0, 2000.0), (33, 3, 400.0, 3000.0), (55, 5, 500.0, 5000.0)], 
     dtype=[('subcase', '<i4'), ('id', '<i4'), ('vonmises', '<f4'), ('maxprincipal', '<f4')]) 
1

numpy_indexedパッケージを使用して、これは簡単なワンライナーだろう:

import numpy_indexed as npi 
ids, maxvonmises = npi.group_by(x.id).max(x.vonmises) 

おそらくパンダと似たパフォーマンスですが、読みやすく、データフォーマットを手元の問題に適応させる必要はありません。