2017-02-21 1 views
4

2つの列があります:pandasデータフレームのCol1、Col2です。 Col1は1〜100の数値を持ち、Col2は0と1を持ちます。値が同じ場合、2番目の変数の並べ替えは一様です。

このデータフレームを並べ替えて、行がCol1でソートされるようにしたいとします。私の場合、私は数百万行を持っているので、間違いなくCol1の値は何度も繰り返されます。

を使用して、Col1に基づいて値を並べ替えることができます。たとえば、これが与えることができる:

Col1 Col2 ... OR ... Col1 Col2 ... OR ... Col1 Col2 
100 0    100 1    100 0 
100 0    100 1    100 0 
100 1    100 1    100 0 
100 0    100 1    100 0 
100 1    100 0    100 1 
100 1    100 0    100 1 
100 1    100 0    100 1 
100 0    100 0    100 1 
99 1    99 1    99 1 
...     ...     ... 

を私は(クイックソート、マージ、など)を使用するソートアルゴリズムに基づいてCol2にのCol1 = 100には多くのディストリビューションが存在する場合があります。

ので、同じように私のCol1が同じ値であるセクションでは、私は、私のCol2にの分布が均一になりたい:

Col1 Col2 
100 0 
100 1 
100 0 
100 1 
100 0 
100 1 
100 0 
100 1 
99 1 
... 

は、Python/numpyの/パンダ/任意の並べ替えの方法があります任意の[他のライブラリ]これを行うことができますか?これを行うことができるアルゴリズムの任意のアイデアですか?

答えて

0

私はその値が順番を表していることを新しい列作成されたと考えることができますアイデア:フォームの入力については

offset_dict = defaultdict(lambda: defaultdict(lambda: 2)) 

def get_offset(row): 
    step = offset_dict[row["Col1"]][row["Col2"]] 
    offset_dict[row["Col1"]][row["Col2"]] += 1 
    return row["Col1"] + 1.0/step 

df["offset"] = df.apply(get_offset, axis=1) 
df = df.sort_values("offset") 

を:

Col1 Col2 
0 100  1 
1 100  1 
2 100  1 
3  99  1 
4 100  0 
5 100  0 
6  99  1 
7  99  0 
8  99  0 
9 100  0 
10 99  0 
11 100  1 
12 100  1 
13 100  0 
14 100  0 

出力は次のようになります。

Col1 Col2  offset 
10 99  0 99.250000 
6  99  1 99.333333 
8  99  0 99.333333 
3  99  1 99.500000 
7  99  0 99.500000 
12 100  1 100.166667 
14 100  0 100.166667 
11 100  1 100.200000 
13 100  0 100.200000 
2 100  1 100.250000 
9 100  0 100.250000 
1 100  1 100.333333 
5 100  0 100.333333 
0 100  1 100.500000 
4 100  0 100.500000 
1

各グループの先頭には、オルタネート0と1の良好なランクを生成する必要があります。

df=pd.DataFrame({'col1':randint(0,100,1000),'col2':randint(0,2,1000),}) 
df.sort_values(['col1','col2'],inplace=True) 
cnt= df.groupby(['col1','col2']).col1.count() 
df['rk']=np.hstack([list(range(n)) for n in cnt]) 
df.sort_values(['col1','rk'],inplace=True) 

いくつかの説明:

まずソートdf:次に

df.sort_values(['col1','col2'],inplace=True) 

各値をカウント:

cnt= df.groupby(['col1','col2']).col1.count() 

とランクを作る:

df['rk']=np.hstack([list(range(n)) for n in cnt]) 

ソリューションは次のようになります。df=pd.DataFrame({'col1':randint(0,100,1000),'col2':randint(0,2,1000),})

df.sort_values(['col1','rk'],inplace=True) 

 col1 col2 rk 
161  0  0 0 
1  0  1 0 
253  0  0 1 
118  0  1 1 
471  0  0 2 
391  0  1 2 
582  0  0 3 
444  0  1 3 
579  0  1 4 
735  0  1 5 
887  0  1 6 
111  1  0 0 
57  1  1 0 
...... 
+0

Easはこれを試して、 'dnt [cntのnに対して' df ['rk'] = sum([list(range)(n)) 'はエラーを返します。確認できますか?私は結果を再現することができませんでした – AbdealiJK

+0

私は入力ミスを避けるためにブロックにコードを入れました。エラーメッセージは何ですか? –

+0

本質的には、リストのリストに対して 'sum'を行うことはできません。 'sum([[1,1]、[2,2]])'も動作しません。これは+: 'int'と 'list'に対してサポートされていないオペランドの型を返します。それはintのリストを必要とします – AbdealiJK

0

我々はCOLによって、その後の並べ替え、cumcountを使用し、カウントすることができます

import pandas as pd 
import numpy as np 
#data from B. M. 

df=pd.DataFrame({'col1':np.random.randint(0,100,1000),'col2':np.random.randint(0,2,1000)}) 

#make a new column, with the cumulative count for each of col1:col2 
df['values'] = df.groupby(['col1','col2']).cumcount() 

#sort by the col1, and values: 
df.sort_values(['col1', 'values']) 

    col1 col2 values 
61 0 1 0 
213 0 0 0 
173 0 1 1 
473 0 0 1 
266 0 1 2 

この意志それらが非常に不均衡であれば失敗します!迅速なハックとして

、アンバランスによってソートする、私たちはそれぞれの値の数で補正し、そのことで私たちのインデックスを分割することができます

#make a new column, with the cumulative count for each of col1:col2 
df['values'] = df.groupby(['col1','col2']).cumcount() 

#sort by the col1, and values: 
df.sort_values(['col1', 'values']) 
#merge in a count of each value 
df = df.merge(df.groupby(['col1', 'col2']).size().reset_index()) 
#make a key of index/count 
df['sortkey'] = df['values']/df[0] 
#sort 
df.sort_values(['col1', 'sortkey']) 

    col1 col2 values sortkey 0 
393 0 0 0 0.000000 3 
812 0 1 0 0.000000 4 
813 0 1 1 0.250000 4 
394 0 0 1 0.333333 3 
814 0 1 2 0.500000 4 
0

それはあなたが「一様分布」によって何を意味するかによって決まります。特定の閾値を超えなければならない特定のテストを適用しますか? 「十分に均一」または「予測不能」にするだけであれば、Col1の各値内でランダム化することができます。

# setup 
import pandas as pd 
import numpy as np 
df=pd.DataFrame({'col1':randint(0,100,1000),'col2':randint(0,2,1000),}) 

# add a column with random numbers 
df['random_col'] = np.random.random(len(df)) 

# two-level sort 
df.sort_values(['col1','random_col']) 
+0

Hmので、私は基本的に(必要ならば、確率的に)0と1がCol1が同じ値を持っているときに均等に分散したいです。私の最終的な目標は、私が取るデータのどんな塊でも(Col1 = 99の行の最初の10%を言ってみよう)平均Col2は同じでなければならないということです。最初の10%は離散データなので、1%-11%と同じではないかもしれません。しかし、確率的には十分だろう。 – AbdealiJK

+1

「どのように均等」についてこの質問をしてくれてありがとう。それは、おそらく問題が明確に定義されていない可能性があることを私に認識させます。そしてこの質問の枠組みを再考するのに役立ちます。 – AbdealiJK

関連する問題