Python-根据条件进行分组组合

时间:2018-08-15 12:51:31

标签: python python-3.x combinations mathematical-optimization itertools

考虑以下数据集,

Name    Age Grade
Person1 18  50
Person2 19  100
Person3 20  0
Person4 21  -25
Person5 22  -125
Person6 23  80
Person7 24  -70

如果我想根据学生的成绩将他们分组在一起,我该怎么做? 我的意思是-我想让一组学生,例如该年级所有学生的成绩总和为0或尽可能接近零。

因此,理想情况下-数据集的答案应类似于-

  1. 第1组----> Person1,Person2,Person4,Person5(因为他们 添加的分数是0)

  2. 第2组----> Person3(因为等级为0)

  3. 第3组----> Person6,Person7(因为加和为10)

我如何继续实现这一目标-

new_dt = pd.read_csv('../tt.csv')

a = list(itertools.chain.from_iterable(
    [[j for i in el for j in i] for el in itertools.combinations(new_dt.values.tolist(),i)]
    for i in range(1, len(new_dt)+1)
    )
    )

out = pd.DataFrame(a)

所以,基本上,我正在使用itertools.combinations找出所有可能的组合

    0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20
0   Person1 18  50                                                                      
1   Person2 19  100                                                                     
2   Person3 20  0                                                                       
3   Person4 21  -25                                                                     
4   Person5 22  -125                                                                        
5   Person6 23  80                                                                      
6   Person7 24  -70                                                                     
7   Person1 18  50  Person2 19  100                                                         
8   Person1 18  50  Person3 20  0                                                           
9   Person1 18  50  Person4 21  -25                                                         
10  Person1 18  50  Person5 22  -125                                                            
11  Person1 18  50  Person6 23  80                                                          
12  Person1 18  50  Person7 24  -70                                                         
13  Person2 19  100 Person3 20  0                                                           
14  Person2 19  100 Person4 21  -25                                                         
15  Person2 19  100 Person5 22  -125                                                            
16  Person2 19  100 Person6 23  80                                                          
17  Person2 19  100 Person7 24  -70                                                         
18  Person3 20  0   Person4 21  -25                                                         
19  Person3 20  0   Person5 22  -125                                                            
20  Person3 20  0   Person6 23  80                                                          
21  Person3 20  0   Person7 24  -70                                                         
22  Person4 21  -25 Person5 22  -125                                                            
23  Person4 21  -25 Person6 23  80                                                          
24  Person4 21  -25 Person7 24  -70                                                         
25  Person5 22  -125    Person6 23  80                                                          
26  Person5 22  -125    Person7 24  -70                                                         
27  Person6 23  80  Person7 24  -70                                                         
28  Person1 18  50  Person2 19  100 Person3 20  0                                               
29  Person1 18  50  Person2 19  100 Person4 21  -25                                             
30  Person1 18  50  Person2 19  100 Person5 22  -125                                                
31  Person1 18  50  Person2 19  100 Person6 23  80                                              
32  Person1 18  50  Person2 19  100 Person7 24  -70                                             
33  Person1 18  50  Person3 20  0   Person4 21  -25                                             
34  Person1 18  50  Person3 20  0   Person5 22  -125                                                
35  Person1 18  50  Person3 20  0   Person6 23  80                                              
36  Person1 18  50  Person3 20  0   Person7 24  -70                                             
37  Person1 18  50  Person4 21  -25 Person5 22  -125                                                
38  Person1 18  50  Person4 21  -25 Person6 23  80                                              
39  Person1 18  50  Person4 21  -25 Person7 24  -70                                             
40  Person1 18  50  Person5 22  -125    Person6 23  80                                              
41  Person1 18  50  Person5 22  -125    Person7 24  -70                                             
42  Person1 18  50  Person6 23  80  Person7 24  -70                                             
43  Person2 19  100 Person3 20  0   Person4 21  -25                                             
44  Person2 19  100 Person3 20  0   Person5 22  -125                                                
45  Person2 19  100 Person3 20  0   Person6 23  80                                              
46  Person2 19  100 Person3 20  0   Person7 24  -70                                             
47  Person2 19  100 Person4 21  -25 Person5 22  -125                                                
48  Person2 19  100 Person4 21  -25 Person6 23  80                                              
49  Person2 19  100 Person4 21  -25 Person7 24  -70                                             
50  Person2 19  100 Person5 22  -125    Person6 23  80                                              
51  Person2 19  100 Person5 22  -125    Person7 24  -70                                             
52  Person2 19  100 Person6 23  80  Person7 24  -70                                             
53  Person3 20  0   Person4 21  -25 Person5 22  -125                                                
54  Person3 20  0   Person4 21  -25 Person6 23  80                                              
55  Person3 20  0   Person4 21  -25 Person7 24  -70                                             
56  Person3 20  0   Person5 22  -125    Person6 23  80                                              
57  Person3 20  0   Person5 22  -125    Person7 24  -70                                             
58  Person3 20  0   Person6 23  80  Person7 24  -70                                             
59  Person4 21  -25 Person5 22  -125    Person6 23  80                                              
60  Person4 21  -25 Person5 22  -125    Person7 24  -70                                             
61  Person4 21  -25 Person6 23  80  Person7 24  -70                                             
62  Person5 22  -125    Person6 23  80  Person7 24  -70                                             
63  Person1 18  50  Person2 19  100 Person3 20  0   Person4 21  -25                                 
64  Person1 18  50  Person2 19  100 Person3 20  0   Person5 22  -125                                    
65  Person1 18  50  Person2 19  100 Person3 20  0   Person6 23  80                                  
66  Person1 18  50  Person2 19  100 Person3 20  0   Person7 24  -70                                 
67  Person1 18  50  Person2 19  100 Person4 21  -25 Person5 22  -125                                    
68  Person1 18  50  Person2 19  100 Person4 21  -25 Person6 23  80                                  
69  Person1 18  50  Person2 19  100 Person4 21  -25 Person7 24  -70                                 
70  Person1 18  50  Person2 19  100 Person5 22  -125    Person6 23  80                                  
71  Person1 18  50  Person2 19  100 Person5 22  -125    Person7 24  -70                                 
72  Person1 18  50  Person2 19  100 Person6 23  80  Person7 24  -70                                 
73  Person1 18  50  Person3 20  0   Person4 21  -25 Person5 22  -125                                    
74  Person1 18  50  Person3 20  0   Person4 21  -25 Person6 23  80                                  
75  Person1 18  50  Person3 20  0   Person4 21  -25 Person7 24  -70                                 
76  Person1 18  50  Person3 20  0   Person5 22  -125    Person6 23  80                                  
77  Person1 18  50  Person3 20  0   Person5 22  -125    Person7 24  -70                                 
78  Person1 18  50  Person3 20  0   Person6 23  80  Person7 24  -70                                 
79  Person1 18  50  Person4 21  -25 Person5 22  -125    Person6 23  80                                  
80  Person1 18  50  Person4 21  -25 Person5 22  -125    Person7 24  -70                                 
81  Person1 18  50  Person4 21  -25 Person6 23  80  Person7 24  -70                                 
82  Person1 18  50  Person5 22  -125    Person6 23  80  Person7 24  -70                                 
83  Person2 19  100 Person3 20  0   Person4 21  -25 Person5 22  -125                                    
84  Person2 19  100 Person3 20  0   Person4 21  -25 Person6 23  80                                  
85  Person2 19  100 Person3 20  0   Person4 21  -25 Person7 24  -70                                 
86  Person2 19  100 Person3 20  0   Person5 22  -125    Person6 23  80                                  
87  Person2 19  100 Person3 20  0   Person5 22  -125    Person7 24  -70                                 
88  Person2 19  100 Person3 20  0   Person6 23  80  Person7 24  -70                                 
89  Person2 19  100 Person4 21  -25 Person5 22  -125    Person6 23  80                                  
90  Person2 19  100 Person4 21  -25 Person5 22  -125    Person7 24  -70                                 
91  Person2 19  100 Person4 21  -25 Person6 23  80  Person7 24  -70                                 
92  Person2 19  100 Person5 22  -125    Person6 23  80  Person7 24  -70                                 
93  Person3 20  0   Person4 21  -25 Person5 22  -125    Person6 23  80                                  
94  Person3 20  0   Person4 21  -25 Person5 22  -125    Person7 24  -70                                 
95  Person3 20  0   Person4 21  -25 Person6 23  80  Person7 24  -70                                 
96  Person3 20  0   Person5 22  -125    Person6 23  80  Person7 24  -70                                 
97  Person4 21  -25 Person5 22  -125    Person6 23  80  Person7 24  -70                                 
98  Person1 18  50  Person2 19  100 Person3 20  0   Person4 21  -25 Person5 22  -125                        
99  Person1 18  50  Person2 19  100 Person3 20  0   Person4 21  -25 Person6 23  80                      
100 Person1 18  50  Person2 19  100 Person3 20  0   Person4 21  -25 Person7 24  -70                     
101 Person1 18  50  Person2 19  100 Person3 20  0   Person5 22  -125    Person6 23  80                      
102 Person1 18  50  Person2 19  100 Person3 20  0   Person5 22  -125    Person7 24  -70                     
103 Person1 18  50  Person2 19  100 Person3 20  0   Person6 23  80  Person7 24  -70                     
104 Person1 18  50  Person2 19  100 Person4 21  -25 Person5 22  -125    Person6 23  80                      
105 Person1 18  50  Person2 19  100 Person4 21  -25 Person5 22  -125    Person7 24  -70                     
106 Person1 18  50  Person2 19  100 Person4 21  -25 Person6 23  80  Person7 24  -70                     
107 Person1 18  50  Person2 19  100 Person5 22  -125    Person6 23  80  Person7 24  -70                     
108 Person1 18  50  Person3 20  0   Person4 21  -25 Person5 22  -125    Person6 23  80                      
109 Person1 18  50  Person3 20  0   Person4 21  -25 Person5 22  -125    Person7 24  -70                     
110 Person1 18  50  Person3 20  0   Person4 21  -25 Person6 23  80  Person7 24  -70                     
111 Person1 18  50  Person3 20  0   Person5 22  -125    Person6 23  80  Person7 24  -70                     
112 Person1 18  50  Person4 21  -25 Person5 22  -125    Person6 23  80  Person7 24  -70                     
113 Person2 19  100 Person3 20  0   Person4 21  -25 Person5 22  -125    Person6 23  80                      
114 Person2 19  100 Person3 20  0   Person4 21  -25 Person5 22  -125    Person7 24  -70                     
115 Person2 19  100 Person3 20  0   Person4 21  -25 Person6 23  80  Person7 24  -70                     
116 Person2 19  100 Person3 20  0   Person5 22  -125    Person6 23  80  Person7 24  -70                     
117 Person2 19  100 Person4 21  -25 Person5 22  -125    Person6 23  80  Person7 24  -70                     
118 Person3 20  0   Person4 21  -25 Person5 22  -125    Person6 23  80  Person7 24  -70                     
119 Person1 18  50  Person2 19  100 Person3 20  0   Person4 21  -25 Person5 22  -125    Person6 23  80          
120 Person1 18  50  Person2 19  100 Person3 20  0   Person4 21  -25 Person5 22  -125    Person7 24  -70         
121 Person1 18  50  Person2 19  100 Person3 20  0   Person4 21  -25 Person6 23  80  Person7 24  -70         
122 Person1 18  50  Person2 19  100 Person3 20  0   Person5 22  -125    Person6 23  80  Person7 24  -70         
123 Person1 18  50  Person2 19  100 Person4 21  -25 Person5 22  -125    Person6 23  80  Person7 24  -70         
124 Person1 18  50  Person3 20  0   Person4 21  -25 Person5 22  -125    Person6 23  80  Person7 24  -70         
125 Person2 19  100 Person3 20  0   Person4 21  -25 Person5 22  -125    Person6 23  80  Person7 24  -70         
126 Person1 18  50  Person2 19  100 Person3 20  0   Person4 21  -25 Person5 22  -125    Person6 23  80  Person7 24  -70

在获得所有分数之后,所有分数都在每第3列中,因此我将

与每3行的总和相加
only_grades['Total'] = only_grades.sum(axis=1)
out['Total'] = only_grades['Total']
out.to_csv('../tt_2.csv')

会在每行上添加一列“总计”,并带有以下输出

Total
50
100
0
-25
-125
80
-70
150
50
25
-75
130
-20
100
75
-25
180
30
-25
-125
80
-70
-150
55
-95
-45
-195
10
150
125
25
230
80
25
-75
130
-20
-100
105
-45
5
-145
60
75
-25
180
30
-50
155
5
55
-95
110
-150
55
-95
-45
-195
10
-70
-220
-15
-115
125
25
230
80
0
205
55
105
-45
160
-100
105
-45
5
-145
60
-20
-170
35
-65
-50
155
5
55
-95
110
30
-120
85
-15
-70
-220
-15
-115
-140
0
205
55
105
-45
160
80
-70
135
35
-20
-170
35
-65
-90
30
-120
85
-15
-40
-140
80
-70
135
35
10
-90
-40
10

当时我想知道,我是否会从这些分组中挑选出来。您如何看待这种方法?以及如何使用“总计”列进行分组,以使原始数据集中的每一行都仅考虑一次而不是多次进行分组。

2 个答案:

答案 0 :(得分:1)

您的答案似乎奏效,但是由于您进行了详尽的搜索,因此其复杂度是指数级的。

这个问题似乎像the subset sum problem,在这里您要查找在较大的集中是否有一个子集的总和为零(这是一个NP问题,因此您不会在其中找到任何完美的解决方案一个多项式时间。如果您不知道,则为an explanation of NP problems

由于已经存在多项式算法来找到子集和问题的近似解,因此我认为对问题进行调整可以使您获得可接受的解。这是the backtracking algorithm I would use

现在让我们来解决您的问题:

1)回溯问题仅适用于正数,因此第一步将是查找集合中的最低成绩。保留它,您将需要多次。一个简单的for循环就可以做到。

2)如果此最低成绩为<0,则可以将其添加到整个成绩中,以得到正成绩。再次for循环将做到这一点。如果最低成绩> = 0,那么除了孤独的学生的成绩为零(并且您有解决方案)之外,您没有任何子集为0。

3)现在,您的问题与the video上的问题完全相同,n为完整集的大小,m为您在步骤< strong> 2)(添加前为零)。执行算法,找到您的子集,然后将其从集合中删除。

4)请注意,您的算法可能会在没有找到所需子集的情况下到达图形的末尾。因此,每次回溯时,请保留该子集及其总和,将其与迄今为止找到的最佳子集进行比较,如果更好,则将其替换。

5)对其余集合应用步骤 3),直到获得剩余集合的总和

这可能不是最佳解决方案,请提出任何改进建议。该算法将优先考虑低距离子集+最后一个不良子集,因此,如果您需要使所有子集近似好,那么这可能不是一个好的解决方案。

如果您每次都在图中快速找到子集,则算法的复杂性将在很大程度上取决于您,因此按等级对学生进行排序可以提高时间的复杂性。而且它将删除步骤 1),因为最小值是第一个元素。

答案 1 :(得分:0)

您很亲近,但我建议您使用输出字典:

z = x^y --> z = exp ( ln(x) * y )

如果需要数据框,强烈建议您使用布尔级数。下面的解决方案假定您已经如上所述构造了一个结果字典。

from itertools import combinations

d = {p: df.loc[df['Name'].isin(p), 'Grade'].sum() \
     for i in range(1, len(df['Name'])+1) \
     for p in combinations(df['Name'], i)}

res = sorted(d.items(), key=lambda x: (abs(x[1]), -len(x[0])))

print(res[:5])

[(('Person1', 'Person2', 'Person3', 'Person4', 'Person5'), 0),
 (('Person1', 'Person2', 'Person4', 'Person5'), 0),
 (('Person3',), 0),
 (('Person1', 'Person3', 'Person5', 'Person6'), 5),
 (('Person2', 'Person3', 'Person4', 'Person7'), 5),
  ...]