我有一个python数据框有三列。
a b c
0 1 2 3
1 1 2 3
2 1 2 8
3 1 5 9
4 1 3 7
5 1 3 4
我想找到a,b,c的所有组合,我的预期结果如下:
[1,2,3]: 2 # from row 0 and row 1
[1,2] : 3 # from row 0 and row 1 and row 2
[1,3] : 4 # from row 0, 1, 4, 5
[1,4] : 1
[1,5] : 1
[1,7] : 1
[1,8] : 1
[1,9] : 1
[2,3] : 2
............
随意使用任何包裹。
import pandas as pd
pd.DataFrame(data=[[1,2,3],[1,2,3],[1,2,8],[1,5,9],[1,3,7],[1,3,4]],columns=['a','b','c'])
答案 0 :(得分:3)
令人厌恶的单行:
In [114]: collections.Counter(map(str, itertools.chain.from_iterable(list(df.apply(lambda x: list(itertools.chain.from_iterable([list(itertools.combinations(x, k)) for k in range(1, 4)])), axis=1).values))))
Out[114]:
Counter({'(1, 2)': 3,
'(1, 2, 3)': 2,
'(1, 2, 8)': 1,
'(1, 3)': 4,
'(1, 3, 4)': 1,
'(1, 3, 7)': 1,
'(1, 4)': 1,
'(1, 5)': 1,
'(1, 5, 9)': 1,
'(1, 7)': 1,
'(1, 8)': 1,
'(1, 9)': 1,
'(1,)': 6,
'(2, 3)': 2,
'(2, 8)': 1,
'(2,)': 3,
'(3, 4)': 1,
'(3, 7)': 1,
'(3,)': 4,
'(4,)': 1,
'(5, 9)': 1,
'(5,)': 1,
'(7,)': 1,
'(8,)': 1,
'(9,)': 1})
一些解释:
首先,感谢lambda
在每一行上应用df.apply(..., axis=1
功能。
lambda
函数会创建行值的所有可能组合,而不管条目数。
我们将所有找到的值合并到一行的每个列表中。第一个itertools.chain.from_iterable
开始的地方。
我们将所有行值合并到一个列表中,使用第二个itertools.chain.from_iterable
。
我们通过collections.Counter
描述结果并获取频率。
修改强>
相同的解决方案,但不使用itertools.chain.from_iterable
In [25]: collections.Counter([str(k) for l in df.apply(lambda x: [c for i in range(1, 4) for c in itertools.combinations(x, i)], axis=1).values for k in l])
这次,我利用列表推导来实现相同的结果,这可能会带来更易读的解决方案。 步骤大致相同,没有"列表合并"阵。
答案 1 :(得分:2)
from cytoolz import concat, mapcat
from functools import partial
from itertools import combinations
c = lambda x, k: combinations(x, k)
pd.value_counts(list(concat(concat(map(
partial(c, x),
range(2, df.shape[1] + 1)
)) for x in df.values.tolist())))
(1, 3) 4
(1, 2) 3
(1, 2, 3) 2
(2, 3) 2
(5, 9) 1
(1, 2, 8) 1
(1, 3, 4) 1
(2, 8) 1
(1, 4) 1
(1, 3, 7) 1
(1, 5, 9) 1
(1, 8) 1
(1, 9) 1
(1, 7) 1
(3, 7) 1
(3, 4) 1
(1, 5) 1
dtype: int64
@ juanpa.arrivillaga建议mapcat
pd.value_counts(list(concat(
(mapcat(partial(c, x), range(2, df.shape[1] + 1)) for x in df.values.tolist())
)))
(1, 3) 4
(1, 2) 3
(1, 2, 3) 2
(2, 3) 2
(5, 9) 1
(1, 2, 8) 1
(1, 3, 4) 1
(2, 8) 1
(1, 4) 1
(1, 3, 7) 1
(1, 5, 9) 1
(1, 8) 1
(1, 9) 1
(1, 7) 1
(3, 7) 1
(3, 4) 1
(1, 5) 1
dtype: int64
答案 2 :(得分:1)
可能有效的方式,一种方式可能是:
import pandas as pd
from itertools import combinations
from collections import Counter
df = pd.DataFrame(data=[[1,2,3],[1,2,3],[1,2,8],[1,5,9],[1,3,7],[1,3,4]],columns=['a','b','c'])
# Get columns combination
# https://stackoverflow.com/a/43348187/5916727
cc = list(combinations(df.columns, 2))
# Append to new list for combinations
tmp_list = []
for columns in cc:
tmp_list.append(list(zip(df[columns[0]], df[columns[1]])))
# https://stackoverflow.com/a/32786226/5916727
tmp_list.append(list(zip(df.a, df.b, df.c)))
# Flatten the list
# https://stackoverflow.com/a/952952/5916727
flat_list = [item for sublist in tmp_list for item in sublist]
print(['{0}:{1}'.format(list(item), count) for item, count in Counter(flat_list).items()])
结果:
['[1, 2]:3',
'[5, 9]:1',
'[1, 2, 8]:1',
'[1, 3]:4',
'[2, 8]:1',
'[1, 3, 4]:1',
'[1, 3, 7]:1',
'[1, 4]:1',
'[1, 2, 3]:2',
'[1, 5]:1',
'[1, 8]:1',
'[2, 3]:2',
'[1, 9]:1',
'[1, 7]:1',
'[3, 7]:1',
'[3, 4]:1',
'[1, 5, 9]:1']