2017-11-30 6 views
2

フィールドにfloatsが含まれている場合、構造化配列の異なるフィールドに含まれるすべてのデータを正規化しようとしています。しかし、私は各フィールドを1つ1つループしていますが、私は警告を受けています。構造化配列の単一フィールドに警告を出さずに書き込む方法

for idt, dt in enumerate(data.dtype.names): 
    if "float32" in data.dtype[idt].name: 
     stds = np.std(data[dt]) 
     means = np.mean(data[dt]) 
     data[dt] = (data[dt] - means)/stds 

最後の行を実行した後、これはポップアップ表示:

FutureWarning:配列へのnumpyのは、あなたが(かもしれない)ことを検出した書き込みがnumpy.diagonalするかで複数のフィールドを選択することにより、 を返さ構造体 配列。このコードは、将来numpyのリリースで破損する可能性があります。 詳細については、numpy.diagonalまたはarrays.indexingリファレンスドキュメントを参照してください。 クイックフィックスは明示的なコピーを作成することです(例えば、 arr.diagonal()。copy()またはarr [['f0'、 'f1']]。copy())。データ[DT] =(データ[DT] - 手段)/性感染症

私は確信してすべてが期待されるようにするためにデバッガで行ごとにそれを実行することができ、例えば:

In[]: data.dtype 
Out[]: dtype([('a', '<f4'), ('b', '<f4'), ('c', '<f4'), ('d', '<i4')]) 
In[]: dt 
Out[]: 'a' 
In[]: data[dt].shape 
Out[]: (2000, 8) 

後警告メッセージ内の提案は、配列をコピーします:

data2 = data.copy() 
for idt, dt in enumerate(data2.dtype.names): 
    if "float32" in data2.dtype[idt].name: 
     stds = np.std(data2[dt]) 
     means = np.mean(data2[dt]) 
     data2[dt] = (data2[dt] - means)/stds 
data = data2 

警告を取り除くためにもっとエレガントな方法はありますか?この場合、コピーはどのように変更されましたか?

+0

「データ」はどのように作成されましたか? – hpaulj

+0

@hpaulj 'data'は' h5py'ライブラリを使ってhdf5ファイルから読み込まれます。オリジナルの作成プロセス私は多くを知らない。しかし、もしあなたが何をしているか教えてくれれば、私はそれについていくつか余分なテストをすることができます。 – Nyps

+1

警告と修正は、 'data'が他の構造化された配列からの多面体選択であることを示唆しています。 'data = bigger_data [['a'、 'b'、 'c'、 'd']]'。問題は、 'data'が' bigger_data'のビューかコピーか、あなたの編集(一度に一つのフィールド)が 'bigger_data'に影響するかどうかです。 – hpaulj

答えて

1
def foo(data): 
    for idt, dt in enumerate(data.dtype.names): 
     if "float32" in data.dtype[idt].name: 
      data[dt] = data[dt] + idt 

In [23]: dt = np.dtype([('a', '<f4'), ('b', '<f4'), ('c', '<f4'), ('d', '<i4')]) 
In [24]: data = np.ones((3,), dtype=dt) 
In [25]: foo(data) 
In [26]: data 
Out[26]: 
array([(1., 2., 3., 1), (1., 2., 3., 1), (1., 2., 3., 1)], 
     dtype=[('a', '<f4'), ('b', '<f4'), ('c', '<f4'), ('d', '<i4')]) 

これは警告なしで動作します。しかし、それは私が警告を受けるデータのマルチフィールド選択を使用しようとした場合:

In [27]: data1 = data[['a','d']] 
In [28]: foo(data1) 
/usr/local/bin/ipython3:4: FutureWarning: Numpy has detected that you (may be) writing to an array returned 
by numpy.diagonal or by selecting multiple fields in a structured 
array. This code will likely break in a future numpy release -- 
see numpy.diagonal or arrays.indexing reference docs for details. 
The quick fix is to make an explicit copy (e.g., do 
arr.diagonal().copy() or arr[['f0','f1']].copy()). 
    import re 

はコピーで動作することはokです:

In [38]: data1 = data[['d','a']].copy() 
In [39]: foo(data1) 
In [40]: data1 
Out[40]: 
array([(1, 2.), (1, 2.), (1, 2.)], 
     dtype=[('d', '<i4'), ('a', '<f4')]) 

(次私はh5pyでこの配列を保存および取得しようとするでしょうそれが違いを作るかどうかを確認します。)h5py

d1 = f['data'] 
foo(d1) # operate directly on the dataset 
data1 = d1[:]; foo(data1) # operate on a copy 
data1 = d1[:,'a','b']   # also a copy 

h5pyデータセットで警告を再現できません。

警告を抑制することもできます。しかし、まず、警告の意味と結果をはっきりと理解する必要があります。

+0

あなたの上のコメントでも示唆されているように、問題は確かに 'data'は既に以前のより大きい' data'の選択です。徹底的な派生をありがとう! – Nyps

関連する問題