#python #pandas #dataframe
Вопрос:
Я тут совсем растерялся. Любая помощь была бы очень признательна!
Это мои текущие данные. Продукт изменился с A. 1 на A. 2. Я хочу, чтобы, когда A. 1 превратится в A. 2, я хочу, чтобы остальные мои данные начинали отсчет времени цикла только для A. 2. То же самое для B. 1 и B. 3.
Вот текущие данные.
--------- ----------- --
| Product | CycleTime | |
--------- ----------- --
| A.1 | 10 | |
--------- ----------- --
| A.1 | 5 | |
--------- ----------- --
| A.1 | 1 | |
--------- ----------- --
| A.1 | 2 | |
--------- ----------- --
| A.1 | 1 | |
--------- ----------- --
| A.2 | 5 | |
--------- ----------- --
| A.2 | 1 | |
--------- ----------- --
| A.1 | 2 | |
--------- ----------- --
| A.1 | 10 | |
--------- ----------- --
| A.2 | 10 | |
--------- ----------- --
| B.1 | 1 | |
--------- ----------- --
| B.1 | 2 | |
--------- ----------- --
| B.1 | 1 | |
--------- ----------- --
| B.3 | 5 | |
--------- ----------- --
| B.1 | 1 | |
--------- ----------- --
| B.3 | 2 | |
--------- ----------- --
| B.1 | 10 | |
--------- ----------- --
Вот что я пытаюсь создать.
--------- ----------- --
| Product | CycleTime | |
--------- ----------- --
| A.1 | 10 | |
--------- ----------- --
| A.1 | 5 | |
--------- ----------- --
| A.1 | 1 | |
--------- ----------- --
| A.1 | 2 | |
--------- ----------- --
| A.1 | 1 | |
--------- ----------- --
| A.2 | 5 | |
--------- ----------- --
| A.2 | 1 | |
--------- ----------- --
| A.2 | 10 | |
--------- ----------- --
| B.1 | 1 | |
--------- ----------- --
| B.1 | 2 | |
--------- ----------- --
| B.1 | 1 | |
--------- ----------- --
| B.3 | 5 | |
--------- ----------- --
| B.3 | 2 | |
--------- ----------- --
Ответ №1:
Если вы отбросите дубликаты и сохраните первые значения, индекс следующего продукта покажет, откуда больше невозможно найти текущий продукт:
find_pos = lambda x: x.drop_duplicates('Product')['Product'].shift().dropna()
.rename_axis('not_valid_after').reset_index()
conds = df.groupby(df['Product'].str.split('.').str[0])
.apply(find_pos).reset_index(drop=True)
print(conds)
# Output:
not_valid_after Product
0 5 A.1 # 5 is the first index of A.2
1 13 B.1 # 13 is the first index of B.3
Теперь вы можете отфильтровать свой фрейм данных:
out = df.drop(conds.apply(lambda x: df.loc[df['Product'] == x['Product']]
.loc[x['not_valid_after']:].index.tolist(),
axis=1).explode().dropna().tolist())
Выход:
>>> out
Product CycleTime
0 A.1 10
1 A.1 5
2 A.1 1
3 A.1 2
4 A.1 1
5 A.2 5
6 A.2 1
9 A.2 10
10 B.1 1
11 B.1 2
12 B.1 1
13 B.3 5
15 B.3 2
Комментарии:
1. Очень умно!!!!
Ответ №2:
установка:
df = pd.DataFrame(
{
"ProductType":["A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "A", "B", "B", "B"],
"Product":["A.1", "A.1", "A.1", "A.1", "A.1", "A.2", "A.2", "A.1", "A.1", "A.2", "B.1", "B.1", "B.1", "B.3", "B.1", "B.3", "B.1"],
"CycleTime":[10,5,1,2,1,5,1,2,10,10,1,2,1,5,1,2,10],
}
)
Создайте заказ между продуктами. Порядок между различными типами продуктов не имеет значения, только внутри каждого типа продукта. Т. е. возьмите несколько частичных заказов и соедините их вместе, чтобы создать общий заказ. Возможно, вам придется сделать это вручную, возможно, вы сможете сделать это программно, это зависит от вашей проблемы.
order = ["A.1", "A.2", "B.1", "B.2", "B.3"]
Создайте карту и ее инверсию, которые свяжут каждый продукт с его позицией в заказе.
mapping = dict(enumerate(order))
inversemapping= {v:k for k,v in mapping.items()}
Идея состоит в том, чтобы для каждого типа продукта сопоставить продукт со значением его заказа и рассчитать совокупный максимум этих значений заказа, прежде чем сопоставлять их с продуктами.
df.groupby("ProductType").apply(lambda d: d["Product"].map(inversemapping).cummax().map(mapping)).values
Вы получите следующий массив numpy:
array(['A.1', 'A.1', 'A.1', 'A.1', 'A.1', 'A.2', 'A.2', 'A.2', 'A.2',
'A.2', 'B.1', 'B.1', 'B.1', 'B.3', 'B.3', 'B.3', 'B.3'],
dtype=object)