У меня есть следующий фрейм данных:
#Load the required libraries
import pandas as pd
#Create dataset
data = {'id': [1, 1, 1, 1, 1,1, 1, 1, 1, 1, 1,
2, 2,
3, 3, 3, 3, 3, 3,
4,
5, 5, 5, 5, 5,5, 5, 5,5],
'cycle': [1,2, 3, 4, 5,6,7,8,9,10,11,
1,2,
1,2, 3, 4, 5,6,
1,
1,2, 3, 4, 5,6,7,8,9,],
'Salary': [7, 7, 7,8,9,10,11,12,13,14,15,
4, 5,
8,9,10,11,12,13,
8,
7, 7,9,10,11,12,13,14,15,],
'Children': ['No', 'Yes', 'Yes', 'Yes', 'Yes', 'No','No', 'Yes', 'Yes', 'Yes', 'No',
'Yes', 'No',
'No','Yes', 'Yes', 'No','No', 'Yes',
'Yes',
'No', 'Yes', 'No', 'No', 'Yes', 'Yes', 'Yes', 'Yes', 'No',],
'Days': [123, 128, 66, 66, 120, 141, 52,96, 120, 141, 52,
96, 120,
15,123, 128, 66, 120, 141,
141,
123, 128, 66, 123, 128, 66, 120, 141, 52,],
}
#Convert to dataframe
df = pd.DataFrame(data)
print("df = \n", df)
Приведенный выше фрейм данных выглядит так:
Здесь каждый идентификатор имеет разные циклы в соответствии со столбцом «цикл». Например,
id-1 имеет максимум 11 циклов.
id-2 имеет максимум 2 цикла.
id-3 имеет максимум 6 циклов.
id-4 имеет максимум 1 цикл.
id-5 имеет максимум 9 циклов.
У меня есть определенный пороговый предел для «циклов». Скажем, цикл_порог = 3
Если максимальное количество циклов для и id <= cycle_threshold, то дублируйте последнюю строку этой группы/идентификатора, пока цикл не достигнет 4.
Например,
Для id-2, поскольку максимальное количество циклов равно 2 (что меньше 3), повторяйте последнюю строку id-2, пока цикл не станет 4.
Для id-4, поскольку максимальное количество циклов равно 1 (что меньше 3), повторяйте последнюю строку id-4, пока цикл не станет 4.
Остальные группы/идентификаторы остаются прежними.
Результат выглядит так:
Может кто-нибудь, пожалуйста, дайте мне знать, как мне выполнить эту задачу в Python?
Вы можете определить id
, сравнив максимальные значения cycle
для групп, а для отфильтрованных групп создайте MultiIndex.from_product и повторите последнее значение с помощью DataFrame.reindex с параметром method='ffill':
cycle_threshold = 3
M = 4
#get maximal cycle per id
s = df.groupby('id')['cycle'].max()
#get id less or equal threshold
ids = s.index[s.le(cycle_threshold)]
#test groups by id match list ids
mask = df['id'].isin(ids)
#create MultiIndex with range(1,M + 1) for filtered groups
df1 = df[mask].set_index(['id','cycle'])
mux = pd.MultiIndex.from_product([ids, range(1, M + 1)], names=['id','cycle'])
#append new groups with sorting by id and cycle
df2 = (pd.concat([df[~mask],
df1.reindex(mux, method='ffill').reset_index()])
.sort_values(['id','cycle'], ignore_index=True))
Другая идея - создать окончательный MultiIndex и переиндексировать все строки:
cycle_threshold = 3
M = 4
s = df.groupby('id')['cycle'].max()
ids = s.index[s.le(cycle_threshold)]
mask = df['id'].isin(ids)
df2 = df.set_index(['id','cycle'])
mux = (pd.MultiIndex.from_product([ids, range(1, 5)],
names=['id','cycle']).append(df2[~mask.to_numpy()].index)
.sort_values())
df2 = df2.reindex(mux, method='ffill').reset_index()
print (df2)
id cycle Salary Children Days
0 1 1 7 No 123
1 1 2 7 Yes 128
2 1 3 7 Yes 66
3 1 4 8 Yes 66
4 1 5 9 Yes 120
5 1 6 10 No 141
6 1 7 11 No 52
7 1 8 12 Yes 96
8 1 9 13 Yes 120
9 1 10 14 Yes 141
10 1 11 15 No 52
11 2 1 4 Yes 96
12 2 2 5 No 120
13 2 3 5 No 120
14 2 4 5 No 120
15 3 1 8 No 15
16 3 2 9 Yes 123
17 3 3 10 Yes 128
18 3 4 11 No 66
19 3 5 12 No 120
20 3 6 13 Yes 141
21 4 1 8 Yes 141
22 4 2 8 Yes 141
23 4 3 8 Yes 141
24 4 4 8 Yes 141
25 5 1 7 No 123
26 5 2 7 Yes 128
27 5 3 9 No 66
28 5 4 10 No 123
29 5 5 11 Yes 128
30 5 6 12 Yes 66
31 5 7 13 Yes 120
32 5 8 14 Yes 141
33 5 9 15 No 52
Создайте фрейм данных с повторяющимися строками, затем соедините его с исходным и, наконец, отсортируйте его:
import numpy as np
cycle_threshold = 3
def fix_cycle(df):
lgt = len(df)
if lgt < cycle_threshold:
df1 = df.reindex(df.index[-1].repeat(cycle_threshold - lgt + 1))
df1['cycle'] += np.arange(len(df1)) + 1
return df1
df1 = df.groupby('id').apply(fix_cycle).droplevel(0)
out = pd.concat([df, df1]).sort_index(kind='stable', ignore_index=True)
Выход:
>>> out
id cycle Salary Children Days
0 1 1 7 No 123
1 1 2 7 Yes 128
2 1 3 7 Yes 66
3 1 4 8 Yes 66
4 1 5 9 Yes 120
5 1 6 10 No 141
6 1 7 11 No 52
7 1 8 12 Yes 96
8 1 9 13 Yes 120
9 1 10 14 Yes 141
10 1 11 15 No 52
11 2 1 4 Yes 96
12 2 2 5 No 120
13 2 3 5 No 120 # <- HERE
14 2 4 5 No 120 # <- HERE
15 3 1 8 No 15
16 3 2 9 Yes 123
17 3 3 10 Yes 128
18 3 4 11 No 66
19 3 5 12 No 120
20 3 6 13 Yes 141
21 4 1 8 Yes 141
22 4 2 8 Yes 141 # <- HERE
23 4 3 8 Yes 141 # <- HERE
24 4 4 8 Yes 141 # <- HERE
25 5 1 7 No 123
26 5 2 7 Yes 128
27 5 3 9 No 66
28 5 4 10 No 123
29 5 5 11 Yes 128
30 5 6 12 Yes 66
31 5 7 13 Yes 120
32 5 8 14 Yes 141
33 5 9 15 No 52
Подробности:
>>> df1
id cycle Salary Children Days
12 2 3 5 No 120
12 2 4 5 No 120
19 4 2 8 Yes 141
19 4 3 8 Yes 141
19 4 4 8 Yes 141
Это не 1, а l (нижний L) и := — оператор моржа (python >= 3.8)
Получил вашу точку зрения. Поскольку у меня python 3.7.6, я получаю сообщение об ошибке.
Я обновил свой ответ для вашей версии Python. Преимущество использования внешнего фрейма данных заключается в том, что вы можете отслеживать, какие строки были добавлены, а какие — из исходного набора данных.
@Corralien... Я получаю сообщение об ошибке в строке "1: = ".... не могли бы вы сообщить мне о проблеме?