我正在尝试解决以下问题。有一个数据框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 :(得分: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
获取所有后续值:
>>> 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
使用GroupBy.apply
将值汇总到列表:
>>> 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]
答案 1 :(得分: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()}))
处理缺失值的变种:
变体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()}))