Как удалить список строк из фрейма данных Pandas?

У меня есть датафрейм df:

>>> df
                  sales  discount  net_sales    cogs
STK_ID RPT_Date                                     
600141 20060331   2.709       NaN      2.709   2.245
       20060630   6.590       NaN      6.590   5.291
       20060930  10.103       NaN     10.103   7.981
       20061231  15.915       NaN     15.915  12.686
       20070331   3.196       NaN      3.196   2.710
       20070630   7.907       NaN      7.907   6.459

Затем я хочу удалить строки с определенными порядковыми номерами, которые указаны в списке, предположим, что здесь [1,2,4], затем слева:

                  sales  discount  net_sales    cogs
STK_ID RPT_Date                                     
600141 20060331   2.709       NaN      2.709   2.245
       20061231  15.915       NaN     15.915  12.686
       20070630   7.907       NaN      7.907   6.459

Как или какая функция может это сделать?

15 ответов

Решение

Используйте DataFrame.drop и передайте ему серию индексных меток:

In [65]: df
Out[65]: 
       one  two
one      1    4
two      2    3
three    3    2
four     4    1


In [66]: df.drop(df.index[[1,3]])
Out[66]: 
       one  two
one      1    4
three    3    2

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

df.drop(df.index[[1,3]], inplace=True)

Поскольку ваш исходный вопрос ничего не возвращает, эту команду следует использовать. http://pandas.pydata.org/pandas-docs/version/0.17.0/generated/pandas.DataFrame.drop.html

Если DataFrame огромен, а количество отбрасываемых строк также велико, то просто по индексу df.drop(df.index[]) занимает слишком много времени.

В моем случае у меня есть многоиндексированный DataFrame с плавающей точкой 100M rows x 3 colsи мне нужно удалить 10k ряды от этого. Самый быстрый метод, который я нашел, довольно нелогично take остальные строки.

Позволять indexes_to_drop быть массивом позиционных индексов для удаления ([1, 2, 4] в вопросе).

indexes_to_keep = set(range(df.shape[0])) - set(indexes_to_drop)
df_sliced = df.take(list(indexes_to_keep))

В моем случае это заняло 20.5sв то время как простой df.drop взял 5min 27s и потреблял много памяти. Результирующий DataFrame такой же.

Я решил это проще - всего за 2 шага.

Шаг 1: Сначала сформируйте фрейм данных с нежелательными строками / данными.

Шаг 2: Используйте индекс этого нежелательного фрейма данных, чтобы удалить строки из исходного фрейма данных.

Пример:

Предположим, у вас есть датафрейм df, который содержит столько столбцов, включая "Возраст", который является целым числом. Теперь предположим, что вы хотите удалить все строки с "Возрастом" в качестве отрицательного числа.

Шаг 1: df_age_negative = df[ df['Age'] < 0 ]

Шаг 2: df = df.drop(df_age_negative.index, axis=0)

Надеюсь, что это намного проще и поможет вам.

Вы также можете передать в DataFrame.drop саму метку (вместо Серии меток индекса):

In[17]: df
Out[17]: 
            a         b         c         d         e
one  0.456558 -2.536432  0.216279 -1.305855 -0.121635
two -1.015127 -0.445133  1.867681  2.179392  0.518801

In[18]: df.drop('one')
Out[18]: 
            a         b         c         d         e
two -1.015127 -0.445133  1.867681  2.179392  0.518801

Что эквивалентно:

In[19]: df.drop(df.index[[0]])
Out[19]: 
            a         b         c         d         e
two -1.015127 -0.445133  1.867681  2.179392  0.518801

Если я хочу отбросить строку, которая имеет, скажем, индекс xЯ бы сделал следующее:

df = df[df.index != x]

Если бы я хотел отбросить несколько индексов (скажем, эти индексы есть в списке unwanted_indices), Я бы сделал:

desired_indices = [i for i in len(df.index) if i not in unwanted_indices]
desired_df = df.iloc[desired_indices]

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

ind_drop = df[df['column_of_strings'].apply(lambda x: x.startswith('Keyword'))].index

А теперь отбросить эти строки, используя их индексы

new_df = df.drop(idx)

Используйте только аргумент индекса для удаления строки:-

df.drop(index = 2, inplace = True)

Для нескольких строк:-

df.drop(index=[1,3], inplace = True)

Определение индекса из логического значения, как описано выше, например

df[df['column'].isin(values)].index

может быть больше памяти, чем определение индекса с помощью этого метода

pd.Index(np.where(df['column'].isin(values))[0])

применяется так

df.drop(pd.Index(np.where(df['column'].isin(values))[0]), inplace = True)

Этот метод полезен при работе с большими кадрами данных и ограниченным объемом памяти.

В комментарии к ответу @theodros-zelleke @j-jones спросил, что делать, если индекс не является уникальным. Мне пришлось иметь дело с такой ситуацией. Я переименовал дубликаты в индексе перед тем, как позвонить drop()а-ля:

dropped_indexes = <determine-indexes-to-drop>
df.index = rename_duplicates(df.index)
df.drop(df.index[dropped_indexes], inplace=True)

где rename_duplicates() это определенная мной функция, которая прошла через элементы индекса и переименовала дубликаты. Я использовал тот же шаблон переименования, что и pd.read_csv() использует столбцы, т. е. "%s.%d" % (name, count), где name это имя строки и count сколько раз это происходило ранее.

Чтобы удалить строки с индексами 1, 2, 4, вы можете использовать:

      df[~df.index.isin([1, 2, 4])]

Оператор тильды ~ отрицает результат метода isin. Другой вариант - отбросить индексы:

      df.loc[df.index.drop([1, 2, 4])]

Посмотрите на следующий фрейм данных df

df

   column1  column2  column3
0        1       11       21
1        2       12       22
2        3       13       23
3        4       14       24
4        5       15       25
5        6       16       26
6        7       17       27
7        8       18       28
8        9       19       29
9       10       20       30

Удалим все строки с нечетным номером в столбце 1

Создайте список всех элементов в column1 и оставьте только те элементы, которые являются четными числами (элементы, которые вы не хотите отбрасывать)

keep_elements = [x for x in df.column1 if x%2==0]

Все строки со значениями [2, 4, 6, 8, 10] в его column1 будет сохранен или не удален.

df.set_index('column1',inplace = True)
df.drop(df.index.difference(keep_elements),axis=0,inplace=True)
df.reset_index(inplace=True)

Мы делаем column1 индексом и удаляем все строки, которые не требуются. Затем мы сбрасываем индекс обратно.df

   column1  column2  column3
0        2       12       22
1        4       14       24
2        6       16       26
3        8       18       28
4       10       20       30

Надеюсь это поможет! Удачного кодирования!!

Как следует из ответа Денниса Голомазова , используя dropчтобы отбросить строки. Вместо этого вы можете выбрать сохранение строк. Допустим, у вас есть список индексов строк, которые нужно отбросить, с именем indices_to_drop. Вы можете преобразовать его в маску следующим образом:

      mask = np.ones(len(df), bool)
mask[indices_to_drop] = False

Вы можете использовать этот индекс напрямую:

      df_new = df.iloc[mask]

В этом методе хорошо то, что mask может поступать из любого источника: это может быть условие, включающее множество столбцов, или что-то еще.

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

Недостатком, конечно же, является то, что вы не можете выполнить сброс на месте с помощью этого метода.

Рассмотрим пример фрейма данных

df =     
index    column1
0           00
1           10
2           20
3           30

мы хотим удалить 2-ю и 3-ю строки индекса.

Подход 1:

df = df.drop(df.index[2,3])
 or 
df.drop(df.index[2,3],inplace=True)
print(df)

df =     
index    column1
0           00
3           30

 #This approach removes the rows as we wanted but the index remains unordered

Подход 2

df.drop(df.index[2,3],inplace=True,ignore_index=True)
print(df)
df =     
index    column1
0           00
1           30
#This approach removes the rows as we wanted and resets the index. 

Это сработало для меня

      # Create a list containing the index numbers you want to remove
index_list = list(range(42766, 42798))
df.drop(df.index[index_list], inplace =True)
df.shape

Это должно удалить все индексы в этом созданном диапазоне.

Другие вопросы по тегам