2016-12-30 57 views
2

我想解決以下問題。有一個數據幀df如何從數據框中提取父節點和後續節點

df = 

ID GROUP_1 GROUP_2 GROUP_3 GROUP_4 
1 AAA  AAA  BBB  CCC 
2 CCC  AAA  CCC  BBB 
3 DDD  CCC  BBB  CCC 
4 ... 

我需要提取組的所有序列和計數。輸出應該是一個(在方括號我想爲給定的父節點的所有可能的後續節點):

result = 
AAA, 3, [AAA,BBB,CCC] 
BBB, 2, [CCC] 
CCC, 3, [AAA,BBB] 
DDD, 1, [CCC] 

我知道如何計算組的唯一出現的次數如下:

df.filter(regex="^GROUP").stack().reset_index(level=1, drop=True).reset_index().drop_duplicates()[0].value_counts() 

它給像這樣的輸出:

AAA 2 
BBB 3 
CCC 3 
DDD 1 

不過,我不知道如何提取所有可能的後續節點沒有重複和計數這些對所有出現(包括重複)。

+0

我不明白,你是怎麼得到'DDD,1,[CCC]'line?或者'CCC,3,[AAA,BBB]'線? –

+0

@RomanPekar:正如你在'df'中看到的那樣,'DDD'的值只有一個可能的後續列值'CCC',並且這樣的序列''只有一個出現(它出現在第3行) 。對於'CCC'也是一樣的:這個值可以有後續列的兩個可能的唯一值,它們是'AAA'和'BBB',總共有3個這樣的對:''(第2行),'' (第2行),''(第3行)。現在更清楚了嗎?謝謝。 – Dinosaurius

回答

2

另一種選擇在這裏:

# melt data frame to long format 
long_df = pd.melt(df, id_vars = "ID", value_name="First") 

# create a shifted subsequent nodes column 
(long_df.assign(Second = long_df.groupby("ID").First.shift(-1)) 

# aggregation grouped by the first column 
.groupby('First').Second 
.agg({'Count': 'count', 'Second': lambda x: x.dropna().unique().tolist()})) 

enter image description here


Variantions與缺失值處理:

變化1

dropna()創建偏移的列之後,這將刪除包含nan任何一對:

(long_df.assign(Second = long_df.groupby("ID").First.shift(-1)).dropna() 
.groupby('First').Second 
.agg({'Count': 'count', 'Second': lambda x: x.unique().tolist()})) 

變形例2

掉落在長格式數據幀缺失值創建偏移柱之前,這將在丟失值之前將缺失值與遺漏值之後連接:

(long_df.dropna().assign(Second = long_df.groupby("ID").First.shift(-1)) 
.groupby('First').Second 
.agg({'Count': 'count', 'Second': lambda x: x.unique().tolist()})) 
+0

什麼是'First'?它在我的例子中對應於'GROUP_'嗎? – Dinosaurius

+0

我在'melt'中將值列重命名爲'First',它對應於GROUP_'列下的值,但是格式爲長格式。 – Psidom

+0

如果某些列「GROUP_X」具有空值,該怎麼辦?此解決方案是否將'NaN'放入'Second'列中的列表中?如何避免它?對不起,我沒有提到這個問題中的重要一點。 – Dinosaurius

2

獲取

>>> df.set_index('ID').stack().reset_index(drop=True) 
0  AAA 
1  AAA 
2  BBB 
3  CCC 
4  CCC 
5  AAA 
6  CCC 
7  BBB 
8  DDD 
9  CCC 
10 BBB 
11 CCC 

開始使用pandas.DataFrame.shift所有後續值的所有可能的值:使用GroupBy.apply

>>> df3 = pd.concat([df2, df2.shift(-1)], axis=1) 
>>> df3.columns = ['k', 'v'] 
>>> df3 = df3[df3['v'].notnull()] 
>>> df3 = df3.drop_duplicates() 
>>> df3 
    k v 
0 AAA AAA 
1 AAA BBB 
2 BBB CCC 
3 CCC CCC 
4 CCC AAA 
5 AAA CCC 
6 CCC BBB 
7 BBB DDD 
8 DDD CCC 

聚合值列表:

>>> df3.groupby('k')['v'].apply(list) 
k 
AAA [AAA, BBB, CCC] 
BBB   [CCC, DDD] 
CCC [BBB, AAA, CCC] 
DDD    [CCC] 

或者

>>> df3.groupby('k').apply(lambda x: pd.Series([len(x), list(x['v'])])) 
    0    1 
k      
AAA 3 [AAA, BBB, CCC] 
BBB 2  [CCC, DDD] 
CCC 3 [BBB, AAA, CCC] 
DDD 1   [CCC] 
+0

不錯。但是,如何計算每個父節點的所有出現次數以便將其放入最終結果? – Dinosaurius

+0

@Dinosaurius看到更新 –

+0

感謝您的解決方案。我接受了Psidom的解決方案,因爲它在我的數據集上速度更快。 – Dinosaurius