Исключение значений во фрейме данных pandas, если они уже встречались в определенном шаблоне - PullRequest
0 голосов
/ 15 октября 2019

Я использую Python 3.4, с пандами, в pycharm

Я разместил свои данные в фрейме данных панд, который выглядит примерно так: enter image description here

import pandas as pd
data = {'step': [1, 2, 2, 3, 4, 4, 4, 5, 5, 4, 5, 6, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8],
        'trials': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]}
temp_df = pd.DataFrame(data=data) 

проблема в том, что «шаг» в строке [15] и шаг в строке [16] соответственно равны 8 и 1, и такая разница недопустима для типа анализа, который я выполняю. Поэтому я хотел бы исключить / удалить / удалить ВСЕ строки между строкой 15 и строкой, в которой значение 'step' возвращается к строке [15], которая в данном случае равна 8, и ее можно найти в строке [23]. [ИЗМЕНЕНО после получения первого ответа] Имейте в виду, что правило заключается в том, что любое последующее значение может быть только +/- 1. Так, например, «шаг» в строке [9] равен 4, что меньше, чем «шаг» встрока [8], которая равна 5. Такая разница допустима, любая разница больше + - 1 - нет.

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

Я искал способы перебирать строки с циклами for и тому подобное, но меня предупреждали, что эти методы очень медленные. И в любом случае я не смог придумать рабочий цикл for.

Мне также не удалось найти разумный программный способ сделать это без циклов и просто использовать панды и какое-то логическое индексирование. Я даже не уверен, возможно ли это без итерации. На данный момент я могу успешно найти все строки, в которых разница между строками [i] и row [i + 1] больше, чем модуль 1 , и логически индексировать это, но я застрял в этой точке.

В конечном итоге я бы создал фрейм данных, в котором исключены строки с 16 по 22.

Ответы [ 2 ]

0 голосов
/ 17 октября 2019

Мое собственное решение, после еще нескольких исследований, представляет собой комбинацию цикла и манипуляции с кадрами.

Сначала я создаю два дополнительных столбца: один со смещением 'step' между каждой строкой и шагом столбца следующей строки, смещенным на одну строку temp_df['shift'] = temp_df.shift(-1);и один, называемый прыжок, с простым логическим индексом, который установлен в True, если какое-либо значение в новом столбце больше 1 temp_df['jump'] = temp_df['diff'] > 1

Затем я в основном создаю индекс всех «прыжков» и запускаюцикл for, где: 1) я извлекаю индекс и значение первого перехода в серии ('curr_idx' и 'curr_value') 2) я копирую подмножество исходного фрейма данных из индекса в конец вновый фрейм данных ('temp_df2' 3) Я ищу индекс первого вхождения значения первого перехода, в новом фрейме данных ('last_value') 4) Я сбрасываю строки в исходном фрейме данных изПервый индекс до последнего индекса ('curr_idx: last_value')

Я также делаю все под «Попробовать:», потому что это решение выдает ошибку, которую мне не удалось устранить. Извините за это.

Вот код:

import pandas as pd
import matplotlib.pyplot as plt

data = {'step': [1, 2, 2, 3, 4, 4, 4, 5, 5, 4, 5, 6, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8]}
temp_df = pd.DataFrame(data=data)

temp_df['diff'] = temp_df['step'] - temp_df['step'].shift(-1)
temp_df['jump'] = temp_df['diff'] > 1
temp_df = temp_df.reset_index(drop=True)

old_df = temp_df

all_values = temp_df[temp_df['jump']]['step']

try:
    for i in range(0,len(all_values)):

        # find all positions at which jump is true
        all_values = temp_df[temp_df['jump']]['step']
        curr_idx = temp_df[temp_df['jump']].index.values.astype(int)[0]
        curr_value = all_values.iloc[0]

        temp_df2 = temp_df.drop(temp_df.index[0:curr_idx+1])
        last_value = temp_df2[temp_df2['step'] == curr_value].index.values.astype(int)[0]

        temp_df = temp_df.drop(temp_df.index[curr_idx:last_value])
        temp_df = temp_df.reset_index(drop=True)
except:
    pass

plt.subplot(121)
ax1 = plt.plot(old_df['step'])

plt.subplot(122)
ax2 = plt.plot(temp_df['step'])

и вот вывод: enter image description here

0 голосов
/ 15 октября 2019

Если кто-то опубликует более короткое решение ', я его удалю, но я обнаружил, что создаю df, который находит первый trials для каждого шага, и если уже было более высокое step в предыдущем trials затем удалите его:

first_apps = temp_df.sort_values(['step', 'trials']).drop_duplicates('step')
first_apps['next_step'] = first_apps['trials'].shift(-1)
temp_df = temp_df.merge(first_apps.drop('trials', axis=1), how='left')
temp_df = temp_df[~(temp_df['trials'] > temp_df['next_step'])].drop('next_step', axis=1)
...