У меня есть фрейм данных, содержащий клинические показания больничных пациентов, например, похожий фрейм данных может выглядеть следующим образом
heartrate pid time
0 67 151 0.0
1 75 151 1.2
2 78 151 2.5
3 99 186 0.0
На самом деле есть еще много столбцов, но я оставлю эти 3, чтобы сделатьПример более краткий.
Я хотел бы «расширить» набор данных.Короче говоря, я хотел бы иметь возможность дать аргумент n_times_back
и еще один аргумент interval
.
Для каждой итерации, которая соответствует for i in range (n_times_back + 1)
, мы делаем следующее:
Создаем новый уникальный pid [OLD ID | i]
(Хотя до тех пор, пока новыйpid
уникален для каждой дублируемой записи, точное имя не очень важно для меня, поэтому смело меняйте это, если вам будет проще)
Для каждого пациента (pid)удалите строки со столбцом time
, который больше, чем final time of that patient - i * interval
.Например, если i * interval = 2.0
и время, связанное с одним pid
, равно [0, 0.5, 1.5, 2.8]
, новое время будет [0, 0.5]
, как final
time - 2.0 = 0.8
итерация
Так как я понимаю, что объяснение этого текста немного грязно, вот пример.
С набором данных выше, если мы допустим n_times_back = 1
и interval=1
, тогда мы получим
heartrate pid time
0 67 15100 0.0
1 75 15100 1.2
2 78 15100 2.5
3 67 15101 0.0
4 75 15101 1.2
5 99 18600 0.0
Для n_times_back = 2
результат будет
heartrate pid time
0 67 15100 0.0
1 75 15100 1.2
2 78 15100 2.5
3 67 15101 0.0
4 75 15101 1.2
5 67 15102 0.0
6 99 18600 0.0
n_times_back = 3
и выше приведет к тому же результату, что и n_times_back = 2
, так как никакие данные пациента не опускаются ниже этой точкисо временем
Я написал код для этого.
def expand_df(df, n_times_back, interval):
for curr_patient in df['pid'].unique():
patient_data = df[df['pid'] == curr_patient]
final_time = patient_data['time'].max()
for i in range(n_times_back + 1):
new_data = patient_data[patient_data['time'] <= final_time - i * interval]
new_data['pid'] = patient_data['pid'].astype(str) + str(i).zfill(2)
new_data['pid'] = new_data['pid'].astype(int)
#check if there is any time index left, if not don't add useless entry to dataframe
if(new_data['time'].count()>0):
df = df.append(new_data)
df = df[df['pid'] != curr_patient] # remove original patient data, now duplicate
df.reset_index(inplace = True, drop = True)
return df
Что касается функциональности, этот код работает как задумано.Тем не менее, это очень медленно.Я работаю с кадром данных из 30 000 пациентов, и код работает уже более 2 часов.
Есть ли способ использовать операции pandas, чтобы ускорить это?Я осмотрелся, но до сих пор мне не удалось воспроизвести эту функцию с помощью функций панд высокого уровня