【发布时间】:2019-03-14 19:30:14
【问题描述】:
此问题与排班或人员配备有关。我正在尝试将各种工作分配给个人(员工)。使用下面的df,
`[Person]` = Individuals (employees)
`[Area]` and `[Place]` = unique jobs
`[On]` = How many unique jobs are occurring at each point in time
所以[Area] 和[Place] 一起构成unique 值,它们是不同的工作。这些值将分配给个人,总体目标是使用尽可能少的个人。 assigned 对任何人来说最独特的值是 3。[On] 显示 [Place] 和 [Area] 的当前 unique 值有多少正在发生。因此,这为我需要多少人提供了具体指南。例如,
1-3 unique values occurring = 1 individual
4-6 unique values occurring = 2 individuals
7-9 unique values occurring = 3 individuals etc
问题:
unique 和 [Area] 和 [Place] 中的值的数量大于 3 给我带来了麻烦。我不能在 assign 第一个 3 unique values 到 individual 1 和接下来的 3 个 unique 值到 individual 2 等处执行 groupby 等。我想在 [Area] 和 @987654342 中对唯一值进行分组@@[Area]。因此,将assign 中的[Area] 中的相同值查看给个人(最多3 个)。然后,如果有 剩余 个值 (
我设想这项工作的方式是:展望未来hour。对于每个新的row 值,script 应该看到有多少值是[On](这表明需要多少个人)。如果unique 的值>3,则它们应该是assigned 乘以grouping 与[Area] 中的相同值。如果有 剩余 值,则无论如何都应该将它们组合成一组 3。
将其放入一个逐步的过程中:
1) 使用[On]Column 来确定@987654356@ 展望未来需要多少人
2) 如果出现超过 3 个 unique 值,请首先在 [Area] 中分配相同的值。
3) 如果有任何 leftover 值,那么无论如何都要寻找组合。
对于下面的 df,[Place] 和 [Area] 出现 9 个 unique 值,并带有 hour。所以我们应该有3个人assigned。当unique 值>3 时,它应该由[Area] 分配,并查看是否出现相同的值。 剩余值应与具有少于 3 个unique 值的其他个体组合。
import pandas as pd
import numpy as np
d = ({
'Time' : ['8:03:00','8:17:00','8:20:00','8:28:00','8:35:00','08:40:00','08:42:00','08:45:00','08:50:00'],
'Place' : ['House 1','House 2','House 3','House 4','House 5','House 1','House 2','House 3','House 2'],
'Area' : ['A','B','C','D','E','D','E','F','G'],
'On' : ['1','2','3','4','5','6','7','8','9'],
'Person' : ['Person 1','Person 2','Person 3','Person 4','Person 5','Person 4','Person 5','Person 6','Person 7'],
})
df = pd.DataFrame(data=d)
这是我的尝试:
def reduce_df(df):
values = df['Area'] + df['Place']
df1 = df.loc[~values.duplicated(),:] # ignore duplicate values for this part..
person_count = df1.groupby('Person')['Person'].agg('count')
leftover_count = person_count[person_count < 3] # the 'leftovers'
# try merging pairs together
nleft = leftover_count.shape[0]
to_try = np.arange(nleft - 1)
to_merge = (leftover_count.values[to_try] +
leftover_count.values[to_try + 1]) <= 3
to_merge[1:] = to_merge[1:] & ~to_merge[:-1]
to_merge = to_try[to_merge]
merge_dict = dict(zip(leftover_count.index.values[to_merge+1],
leftover_count.index.values[to_merge]))
def change_person(p):
if p in merge_dict.keys():
return merge_dict[p]
return p
reduced_df = df.copy()
# update df with the merges you found
reduced_df['Person'] = reduced_df['Person'].apply(change_person)
return reduced_df
df1 = (reduce_df(reduce_df(df)))
这是输出:
Time Place Area On Person
0 8:03:00 House 1 A 1 Person 1
1 8:17:00 House 2 B 2 Person 1
2 8:20:00 House 3 C 3 Person 1
3 8:28:00 House 4 D 4 Person 4
4 8:35:00 House 5 E 5 Person 5
5 8:40:00 House 1 D 6 Person 4
6 8:42:00 House 2 E 7 Person 5
7 8:45:00 House 3 F 8 Person 5
8 8:50:00 House 2 G 9 Person 7
这是我的预期输出:
Time Place Area On Person
0 8:03:00 House 1 A 1 Person 1
1 8:17:00 House 2 B 2 Person 1
2 8:20:00 House 3 C 3 Person 1
3 8:28:00 House 4 D 4 Person 2
4 8:35:00 House 5 E 5 Person 3
5 8:40:00 House 6 D 6 Person 2
6 8:42:00 House 2 E 7 Person 3
7 8:45:00 House 3 F 8 Person 2
8 8:50:00 House 2 G 9 Person 3
关于我希望如何获得此输出的说明:
Index 0: One `unique` value occurring. So `assign` to individual 1
Index 1: Two `unique` values occurring. So `assign` to individual 1
Index 2: Three `unique` values occurring. So `assign` to individual 1
Index 3: Four `unique` values on. So `assign` to individual 2
Index 4: Five `unique` values on. This one is a bit tricky and hard to conceptualise. But there is another `E` within an `hour`. So `assign` to a new individual so it can be combined with the other `E`
Index 5: Six `unique` values on. Should be `assigned` with the other `D`. So individual 2
Index 6: Seven `unique` values on. Should be `assigned` with other `E`. So individual 3
Index 7: Eight `unique` values on. New value in `[Area]`, which is a _leftover_. `Assign` to either individual 2 or 3
Index 8: Nine `unique` values on. New value in `[Area]`, which is a _leftover_. `Assign` to either individual 2 or 3
示例 2:
d = ({
'Time' : ['8:03:00','8:17:00','8:20:00','8:28:00','8:35:00','8:40:00','8:42:00','8:45:00','8:50:00'],
'Place' : ['House 1','House 2','House 3','House 1','House 2','House 3','House 1','House 2','House 3'],
'Area' : ['X','X','X','X','X','X','X','X','X'],
'On' : ['1','2','3','3','3','3','3','3','3'],
'Person' : ['Person 1','Person 1','Person 1','Person 1','Person 1','Person 1','Person 1','Person 1','Person 1'],
})
df = pd.DataFrame(data=d)
我收到一个错误:
IndexError: index 1 is out of bounds for axis 1 with size 1
在这一行:
df.loc[:,'Person'] = df['Person'].unique()[assignedPeople]
但是,如果我将 Person 更改为 1、2、3 重复,它会返回以下内容:
'Person' : ['Person 1','Person 2','Person 3','Person 1','Person 2','Person 3','Person 1','Person 2','Person 3'],
Time Place Area On Person
0 8:03:00 House 1 X 1 Person 1
1 8:17:00 House 2 X 2 Person 1
2 8:20:00 House 3 X 3 Person 1
3 8:28:00 House 1 X 3 Person 2
4 8:35:00 House 2 X 3 Person 2
5 8:40:00 House 3 X 3 Person 2
6 8:42:00 House 1 X 3 Person 3
7 8:45:00 House 2 X 3 Person 3
8 8:50:00 House 3 X 3 Person 3
预期输出:
Time Place Area On Person
0 8:03:00 House 1 X 1 Person 1
1 8:17:00 House 2 X 2 Person 1
2 8:20:00 House 3 X 3 Person 1
3 8:28:00 House 1 X 3 Person 1
4 8:35:00 House 2 X 3 Person 1
5 8:40:00 House 3 X 3 Person 1
6 8:42:00 House 1 X 3 Person 1
7 8:45:00 House 2 X 3 Person 1
8 8:50:00 House 3 X 3 Person 1
示例 2 的主要内容是:
1) There are <3 unique values on so assign to individual 1
【问题讨论】:
-
我对所需的输出感到困惑,为什么 Person 4 不是您所需输出的一部分?我认为问题的限制不是很清楚
-
@PeterJames123 你的输出看起来不错。根据需要,您总共有 3 个人。(Person1、Person2 和 Person4)。为什么你不能使用这个输出?如果此人的顺序很重要,您可以检查顺序并查看 Person3 缺失,然后您可以将 Person4 替换为 Person3 并继续......
-
在您的问题中,您说值的唯一性取决于
Hour和Area。同时您说您的输入d有 9 个唯一值“在一小时内发生”,即使它是将 9 个值(观察值)分成多个小时和 7 个唯一区域?我不跟。您的问题中也有许多不同的解释(在评论部分)。我认为审查它们并选择一个对您是有益的。 -
我也很难理解问题。我认为如果您提供一些背景信息可能会有所帮助。每一行数据代表什么?有哪些地方,有哪些人?这是关于为资源分配员工吗?
-
我不怀疑我(和其他人)误解了您的标准,但也许这表明您的描述不清楚?我会接受@TomWojcik:s 的建议并重组你的问题。关注 1) 输入和 2) 预期输出。您现在显示了多个输入(根据我的计数为 3 个),这让事情更加混乱。尝试显示代表您的问题的一个输入和一个输出。
标签: python pandas numpy dataframe assign