Удалите строки с повторяющимися индексами (Pandas DataFrame и TimeSeries)

Я читаю некоторые автоматические метеорологические данные из Интернета. Наблюдения происходят каждые 5 минут и собираются в ежемесячные файлы для каждой метеостанции. Когда я закончил разбор файла, DataFrame выглядит примерно так:

Sta Precip1hr Precip5min Temp DewPnt WindSpd WindDir AtmPress Date 2001-01-01 00:00:00 KPDX 0 0 4 3 0 0 30.31 2001-01-01 00:05:00 KPDX 0 0 4 3 0 0 30.30 2001-01-01 00:10:00 KPDX 0 0 4 3 4 80 30.30 2001-01-01 00:15:00 KPDX 0 0 3 2 5 90 30.30 2001-01-01 00:20:00 KPDX 0 0 3 2 10 110 30.28 

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

 import pandas import datetime startdate = datetime.datetime(2001, 1, 1, 0, 0) enddate = datetime.datetime(2001, 1, 1, 5, 0) index = pandas.DatetimeIndex(start=startdate, end=enddate, freq='H') data = {'A' : range(6), 'B' : range(6)} data1 = {'A' : [20, -30, 40], 'B' : [-50, 60, -70]} df1 = pandas.DataFrame(data=data, index=index) df2 = pandas.DataFrame(data=data1, index=index[:3]) df3 = df1.append(df2) df3 AB 2001-01-01 00:00:00 20 -50 2001-01-01 01:00:00 -30 60 2001-01-01 02:00:00 40 -70 2001-01-01 03:00:00 3 3 2001-01-01 04:00:00 4 4 2001-01-01 05:00:00 5 5 2001-01-01 00:00:00 0 0 2001-01-01 01:00:00 1 1 2001-01-01 02:00:00 2 2 

И поэтому мне нужно df3 для равномерного старта:

  AB 2001-01-01 00:00:00 0 0 2001-01-01 01:00:00 1 1 2001-01-01 02:00:00 2 2 2001-01-01 03:00:00 3 3 2001-01-01 04:00:00 4 4 2001-01-01 05:00:00 5 5 

Я думал, что добавление столбца номеров строк ( df3['rownum'] = range(df3.shape[0]) ) поможет мне выбрать самую нижнюю строку для любого значения DatetimeIndex , но я застрял на вычислении выполните group_by или pivot (или?), чтобы сделать эту работу.

4 Solutions collect form web for “Удалите строки с повторяющимися индексами (Pandas DataFrame и TimeSeries)”

Простое решение – использовать drop_duplicates

 df4 = df3.drop_duplicates(subset='rownum', keep='last') 

Для меня это быстро срабатывало на больших наборах данных.

Для этого требуется, чтобы «rownum» был столбцом с дубликатами. В модифицированном примере «rownum» не имеет дубликатов, поэтому ничего не устраняется. Мы действительно хотим, чтобы «cols» были установлены в индекс. Я не нашел способ сказать drop_duplicates, чтобы рассматривать индекс только.

Вот решение, которое добавляет индекс в качестве столбца dataframe, удаляет дубликаты, а затем удаляет новый столбец:

 df3 = df3.reset_index().drop_duplicates(subset='index', keep='last').set_index('index') 

И если вы хотите, чтобы вещи вернулись в правильном порядке, просто вызовите sort по кадру данных.

 df3 = df3.sort() 

Изменить: лучший ответ ниже

Взгляните на ответ n8yoder, используя «duplicated». Я не считаю, что это существовало в более старых версиях Pandas, где этот ответ все еще может применяться.

Я бы предложил использовать дублированный метод для самого индекса Pandas:

 df3 = df3[~df3.index.duplicated(keep='first')] 

В то время как все остальные методы работают, принятый в настоящее время ответ , безусловно, наименее эффективен для предоставленного примера. Кроме того, в то время как метод groupby только немного менее эффективен, я считаю, что дублированный метод является более читаемым.

Используя предоставленные данные:

 >>> %timeit df3.reset_index().drop_duplicates(subset='index', keep='first').set_index('index') 1000 loops, best of 3: 1.54 ms per loop >>> %timeit df3.groupby(df3.index).first() 1000 loops, best of 3: 580 µs per loop >>> %timeit df3[~df3.index.duplicated(keep='first')] 1000 loops, best of 3: 307 µs per loop 

Обратите внимание, что вы можете сохранить последний элемент, изменив аргумент keep.

Следует также отметить, что этот метод также работает с MultiIndex (используя df1, как указано в примере Павла):

 >>> %timeit df1.groupby(level=df1.index.names).last() 1000 loops, best of 3: 771 µs per loop >>> %timeit df1[~df1.index.duplicated(keep='last')] 1000 loops, best of 3: 365 µs per loop 

О, мой. Это на самом деле так просто!

 grouped = df3.groupby(level=0) df4 = grouped.last() df4 AB rownum 2001-01-01 00:00:00 0 0 6 2001-01-01 01:00:00 1 1 7 2001-01-01 02:00:00 2 2 8 2001-01-01 03:00:00 3 3 3 2001-01-01 04:00:00 4 4 4 2001-01-01 05:00:00 5 5 5 

Последующее редактирование 2013-10-29 В случае, когда у меня довольно сложный MultiIndex , я думаю, что предпочитаю groupby подход. Вот простой пример для потомков:

 import numpy as np import pandas # fake index idx = pandas.MultiIndex.from_tuples([('a', letter) for letter in list('abcde')]) # random data + naming the index levels df1 = pandas.DataFrame(np.random.normal(size=(5,2)), index=idx, columns=['colA', 'colB']) df1.index.names = ['iA', 'iB'] # artificially append some duplicate data df1 = df1.append(df1.select(lambda idx: idx[1] in ['c', 'e'])) df1 # colA colB #iA iB #aa -1.297535 0.691787 # b -1.688411 0.404430 # c 0.275806 -0.078871 # d -0.509815 -0.220326 # e -0.066680 0.607233 # c 0.275806 -0.078871 # <--- dup 1 # e -0.066680 0.607233 # <--- dup 2 

и вот важная часть

 # group the data, using df1.index.names tells pandas to look at the entire index groups = df1.groupby(level=df1.index.names) groups.last() # or .first() # colA colB #iA iB #aa -1.297535 0.691787 # b -1.688411 0.404430 # c 0.275806 -0.078871 # d -0.509815 -0.220326 # e -0.066680 0.607233 

К сожалению, я не думаю, что Pandas позволяет отказаться от индексов. Я бы предложил следующее:

 df3 = df3.reset_index() # makes date column part of your data df3.columns = ['timestamp','A','B','rownum'] # set names df3 = df3.drop_duplicates('timestamp',take_last=True).set_index('timestamp') #done! 
  • Python Pandas реплицирует строки в dataframe
  • Python Pandas подсчет и суммирование конкретных условий
  • Pandas: создать новый столбец в df со случайными целыми числами от диапазона
  • Как группировать серию по значениям в пандах?
  • Как создать новый столбец на основе условий других столбцов в пандах?
  • Как группировать строки и извлекать средние значения
  • Чтение нескольких CSV-файлов в Python Pandas Dataframe
  • pandas: Как выбрать строки на основе, если X число столбцов больше числа?
  • Присвоить значение подмножеству строк в кадре данных Pandas
  • Pandas Plots: отдельный цвет для выходных, довольно время печати по оси x
  • Преобразовать панды «Серия парных массивов» в «двухколонный DataFrame»?
  •  
    Interesting Posts for Van-Lav

    Должен ли я добавлять файлы миграции Django в файл .gitignore?

    Любая библиотека поддержки векторной машины python, которая позволяет онлайн-обучение?

    NumPy genfromtxt: правильно использовать fill_missing

    Расшифруйте ошибку, соединяющую экземпляр mongo, размещенный в <project> .meteor.com

    Дизайн виртуальной пробной комнаты

    сравнить объект с пустым кортежем с оператором 'is' в Python 2.x

    Преобразование JSON в Python dict

    Пиза (XHTML -> PDF) в Django не будет отображать изображения в PDF

    Проверка наличия списка дубликатов списков

    кодировать двоичный код на аудио-питон или C

    Как я могу динамически выполнять функцию в текущей области и добавлять ее как свойство вызывающей функции?

    Взаимодействие с консольным приложением Windows через Python

    Лучший способ ссылки на модель пользователя в Django> = 1.5

    Как отлаживать возвышенные плагины во время разработки

    Python: Можно ли преобразовать структуру ctypes в словарь?

    Python - лучший язык программирования в мире.