考虑以下数据集,
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组----> Person1,Person2,Person4,Person5(因为他们 添加的分数是0)
第2组----> Person3(因为等级为0)
我如何继续实现这一目标-
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
当时我想知道,我是否会从这些分组中挑选出来。您如何看待这种方法?以及如何使用“总计”列进行分组,以使原始数据集中的每一行都仅考虑一次而不是多次进行分组。
答案 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),
...]