Как удалить список строк из фрейма данных 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
Это должно удалить все индексы в этом созданном диапазоне.