Панды: дублирование записей в кадре данных, когда столбец больше или равен 0 - PullRequest
0 голосов
/ 11 июня 2018

У меня есть фрейм данных, содержащий клинические показания больничных пациентов, например, похожий фрейм данных может выглядеть следующим образом

   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, чтобы ускорить это?Я осмотрелся, но до сих пор мне не удалось воспроизвести эту функцию с помощью функций панд высокого уровня

1 Ответ

0 голосов
/ 18 июня 2018

закончилось использованием функции groupby и прерыванием, когда больше не было времени, а также созданием столбца «index», который я сливаю со столбцом «pid» в конце.

def expand_df(group, n_times, interval):
    df = pd.DataFrame()
    final_time = group['time'].max()
    for i in range(n_times + 1):
        new_data = group[group['time'] <= final_time - i * interval]
        new_data['iteration'] = str(i).zfill(2)
        #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)
        else:
            break
    return df

new_df = df.groupby('pid').apply(lambda x : expand_df(x, n_times_back, interval))
new_df = new_df.reset_index(drop=True)
new_df['pid'] = new_df['pid'].map(str) + new_df['iteration']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...