2016-08-26 14 views
1

2つの列Label1とLabel2があります。どちらもクラスターラベルで、異なる方法を使用しています。2つの他の列に基づいて列の値を決定します

Label1 Label2 
0 0 1024 
1 1 1024 
2 2 1025 
3 3 1026 
4 3 1027 
5 4 1028 

この2つの列に基づいて最終的なクラスターラベルを取得します。各行を比較すると、これらの2つのラベルのうちの1つが同じである限り、それらは同じクラスタにあります。

たとえば、行0と行1はラベル2を共有し、行3と行4はラベル1を共有します。したがって、同じグループの行0と行1と同じグループの行3と行4になります。だから私はしたいのですが結果:?

Label1 Label2 Cluster ID 
0 0 1024 0 
1 1 1024 0 
2 2 1025 1 
3 3 1026 2 
4 3 1027 2 
5 4 1028 3 

は、これを行うための最善の方法は何 任意の助けいただければ幸いです。

編集:私は良い例を挙げなかったと思います。 Acutally、ラベルは任意の順序である必要はありません。

Label1 Label2 
0 0 1024 
1 1 1023 
2 2 1025 
3 3 1024 
4 3 1027 
5 4 1022 
+4

最高の試みのためにコードを投稿してください。ありがとう – lrnzcig

+0

詳細については、このリンクを確認してください - http://stackoverflow.com/help/how-to-ask –

答えて

2

試してください:npを使用してください。ここをクリックしてpandas.duplicated

df    = df.sort_values(['Label1', 'Label2']) 
df['Cluster'] = np.where((df.Label1.duplicated()) | (df.Label2.duplicated()),0,1).cumsum() 
print df 

     Label1 Label2 Cluster 
0  0 1024  1 
1  1 1024  1 
2  2 1025  2 
3  3 1026  3 
4  3 1027  3 
5  4 1028  4 
+0

ありがとうございます。私は質問を更新した、私の問題は、ラベルの列が単調ではないということです。同じラベルが行1に表示され、次に行100に表示され、同じグループとしてクラスター化される必要があります。助言がありますか。 – aidsj

+0

私はそれをテストしました、それは注文に依存しました。 df = pd.DataFrame( {'Label1':[0,1,2,2,1,3]、 'Label2':[1023,1024,1025,1026,1027,1028])を指定します。結果:1,2,3,3,3,4。ただし、行1と行4は同じグループ内にある必要があります。とにかく助けてくれてありがとう。 – aidsj

+0

はい、あなたは大丈夫です、それを修正しました、cumsumの使用は注文に基づいています、幸運 – Merlin

1

ない私が正しくあなたの質問を理解してきたが、ここでクラスタを識別するための可能な方法があります確認してください:ここでは

import pandas as pd 
import collections 

df = pd.DataFrame(
    {'Label1': [0, 1, 2, 3, 3, 4], 'Label2': [1024, 1024, 1025, 1026, 1027, 1028]}) 
df['Cluster ID'] = [0] * 6 

counter1 = {k: v for k, v in collections.Counter(
    df['Label1']).iteritems() if v > 1} 
counter1 = counter1.keys() 
counter2 = {k: v for k, v in collections.Counter(
    df['Label2']).iteritems() if v > 1} 
counter2 = counter2.keys() 

len1 = len(counter1) 
len2 = len(counter2) 
index_cluster = len1 + len2 

for index, row in df.iterrows(): 
    if row['Label2'] in counter2: 
     df.loc[index, 'Cluster ID'] = counter2.index(row['Label2']) 
    elif row['Label1'] in counter1: 
     df.loc[index, 'Cluster ID'] = counter1.index(row['Label1']) + len2 
    else: 
     df.loc[index, 'Cluster ID'] = index_cluster 
     index_cluster += 1 

print df 
+0

ありがとうございます。少し丁寧に説明しますか? – aidsj

1

は、あなたがこれを実装する方法です。二つの列に対して同じ値の

  1. チェック前の行

  2. 値のいずれかが同じである場合は、クラスタ番号をインクリメントしていないと値がいずれも同じでない場合は、クラスタリストに

  3. を追加し、クラスタ番号をインクリメントし、カラムとしてクラスタリストの追加クラスタリストに

  4. を追加データフレームに変換します。

コード:

import pandas as pd 

df=pd.DataFrame([[0,1,2,3,4,5],[0,1,2,3,3,4],[1024,1024,1025,1026,1027,1028]]).T 
cluster_num = 0 
cluster_list = [] 
for i,row in df.iterrows(): 
    if i!=0: 
     # check previous row 
     if df.loc[i-1][1]==row[1] or df.loc[i-1][2]==row[2]: 
      # add to previous cluster 
      cluster_list.append(cluster_num) 
     else: 
      # create new cluster 
      cluster_num+=1 
      cluster_list.append(cluster_num) 
    else: 
     cluster_list.append(cluster_num) 

#Add the list as column 
df.insert(3,3,cluster_list) 
2

IIUC、あなたは可能性がグループのクラスタを次のように:

が行の差をとると、それは次の行だ、0と一番上の行を充填し、それをの認定両方のラベル[1と2]の累積合計。

In [2]: label1_ = df['Label1'].diff().fillna(0).cumsum() 

In [3]: label2_ = df['Label2'].diff().fillna(0).cumsum() 

ラベルを新しいデータフレームに連結し、ラベル[1と2]の両方で複製値を別々に削除します。 reset_indexのあとに、デフォルトの整数インデックスを戻します。

新しい列であるクラスタIDにインデックス値を割り当てます。

In [5]: df_['Cluster_ID'] = df_.index 

In [6]: df_.set_index('index', inplace=True) 

In [7]: df['Cluster_ID'] = df_['Cluster_ID'] 

それの前の有限値でNan値を交換し、整数として最終的な答えをキャスト。

In [8]: df.fillna(method='ffill').astype(int) 
Out[8]: 
    Label1 Label2 Cluster_ID 
0  0 1024   0 
1  1 1024   0 
2  2 1025   1 
3  3 1026   2 
4  3 1027   2 
5  4 1028   3 
関連する問題