n次元ベクトルのベクトルを表すnumpyの配列(?、n)があります。ベクトルの行列の最も頻繁な行またはモードを見つける - Python/NumPy
最も頻繁な行を探したいと思います。
これまでのところ、すべてのエントリを繰り返し処理してカウントを保存するのが最善の方法だと思われますが、numpyやscipyにはこのタスクを実行するための何かが組み込まれていないことがわかります。
n次元ベクトルのベクトルを表すnumpyの配列(?、n)があります。ベクトルの行列の最も頻繁な行またはモードを見つける - Python/NumPy
最も頻繁な行を探したいと思います。
これまでのところ、すべてのエントリを繰り返し処理してカウントを保存するのが最善の方法だと思われますが、numpyやscipyにはこのタスクを実行するための何かが組み込まれていないことがわかります。
ここでかなり効率的であるべきNumPy views
を、使用したアプローチだ -
def mode_rows(a):
a = np.ascontiguousarray(a)
void_dt = np.dtype((np.void, a.dtype.itemsize * np.prod(a.shape[1:])))
_,ids, count = np.unique(a.view(void_dt).ravel(), \
return_index=1,return_counts=1)
largest_count_id = ids[count.argmax()]
most_frequent_row = a[largest_count_id]
return most_frequent_row
サンプル実行 -
In [45]: # Let's have a random arrayb with three rows(2,4,8) and two rows(1,7)
...: # being duplicated. Thus, the most freequent row must be 2 here.
...: a = np.random.randint(0,9,(9,5))
...: a[4] = a[8]
...: a[2] = a[4]
...:
...: a[1] = a[7]
...:
In [46]: a
Out[46]:
array([[8, 8, 7, 0, 7],
[7, 8, 2, 6, 1],
[2, 2, 5, 7, 6],
[6, 5, 8, 8, 5],
[2, 2, 5, 7, 6],
[5, 7, 3, 6, 3],
[2, 8, 7, 2, 0],
[7, 8, 2, 6, 1],
[2, 2, 5, 7, 6]])
In [47]: mode_rows(a)
Out[47]: array([2, 2, 5, 7, 6])
素晴らしい、ありがとう!私はどのように正確に動作するかを把握しようとしています。どのようにしてview()は配列をすべての要素が実際にnumpyには見えない配列である表現にするのですか?具体的には、np.ravel()によってすべてがすべての値の1つの長い配列にフラット化されるわけではありません。 – dant
@dantまあ、各行は1つのスカラーとして潰れていますが、寸法はそのままです。したがって、 '(m、n)'配列は '(m、1)'配列になります。これは 'a.view(void_dt)'で行われます。次に、 'ravel()'を使って '(m)'配列にします。これは1D配列を 'np.unique'で使うことができます。 – Divakar
@dantそれを確認するには、 'a.view(void_dt).ravel()'を 'a.view(void_dt)[:, 0]'に置き換えてください。 – Divakar
あなたはパンダを使用することができるしている場合は、ここthis answerから大きく描く一つのアプローチは、です:
import numpy as np
import pandas as pd
# generate sample data
ncol = 5
nrow = 20000
matrix = np.random.randint(0,ncol,ncol*nrow).reshape(nrow,ncol)
df = pd.DataFrame(matrix)
df.head()
0 1 2 3 4
0 3 0 4 4 4
1 4 0 0 2 0
2 3 3 2 0 0
3 0 3 4 3 3
4 1 1 3 3 3
# count duplicated rows
(df.groupby(df.columns.tolist())
.size()
.sort_values(ascending=False))
出力:
0 1 2 3 4
4 2 2 1 1 17
2 2 4 2 3 16
3 2 1 2 2 15
1 2 4 3 15
..
4 1 3 0 1 1
1 2 3 0 4 1
最も頻繁行は、この出力の一番上の行であります。頻度カウントは右端の列です。
感謝、私は以前のパンダのソリューションを見つけることができましたが、私の現在の仕事の目的ではライブラリを使用できません。 – dant
numpy_indexedパッケージ(dsiclaimer:私はその作者だが)まさにこれを行う機能を持っていますこれは、任意の数のディメンションで動作します。
import numpy_indexed as npi
row = npi.mode(arr)
フードの下では、アルゴリズムと複雑さの点でDivakarのソリューションに似ていますが、いくつかの鐘や笛があります。 'weights'と 'return_indices' kwargsを参照してください。
誰かがnumpyの拡張機能に取り組んでいるのを見るのは素晴らしいことです。うまくいけば、それはいつかソースに終わるだろう:) – dant
それは私の元の意図だった。しかし、Pythonパッケージ管理が近年成熟したことを考えると、独自のリリースサイクルを持つ別個のミニパッケージが本当に意味をなさないと思います。 –
どういう意味ですか? ['scipy.stats.mode'](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.mode.html)が存在します。 – Blender
@Blender:自然に最も一般的な_row _を見つけ出すのかどうかはわかりませんが、_values_のモードを指定された軸に沿って返します。 – DSM
@DSM:そうです。 most_common()[0] 'は600kの3ベクトルを約1秒で処理しますが、より効率的な解決策が存在すると確信しています。 – Blender