Попытка удалить несколько строк из кадра данных Pandas, но удаляется больше строк, чем предполагалось
У меня есть список, to_delete, индексов строк, которые я хочу удалить из обоих моих двух кадров данных Pandas, df1 и df2. У них по 500 рядов. to_delete имеет 50 записей. Я запускаю это:
df1.drop(df1.index[to_delete], inplace=True)
df2.drop(df2.index[to_delete], inplace=True)
Но это приводит к тому, что df1 и df2 имеют по 250 строк каждая. Он удаляет 250 строк из каждой, а не 50 конкретных строк, которые я хочу...
to_delete упорядочено в порядке убывания.
Полный метод:
def method(results):
#results is a 500 x 1 matrix of 1's and -1s
global df1, df2
deletions = []
for i in xrange(len(results)-1, -1, -1):
if results[i] == -1:
deletions.append(i)
df1.drop(df1.index[deletions], inplace=True)
df2.drop(df2.index[deletions], inplace=True)
Любые предложения относительно того, что я делаю неправильно?
(Я также пытался использовать .iloc
вместо .index
и удаление в if statement
вместо добавления в список первым.
1 ответ
Ваши значения индекса не являются уникальными, и когда вы используете drop
он удаляет все строки с этими значениями индекса. to_delete
может иметь длину 50, но было 250 строк, которые имели эти конкретные значения индекса.
Рассмотрим пример
df = pd.DataFrame(dict(A=range(10)), [0, 1, 2, 3, 4] * 2)
df
A
0 0
1 1
2 2
3 3
4 4
0 5
1 6
2 7
3 8
4 9
Допустим, вы хотите удалить первый, третий и четвертый ряды.
to_del = [0, 2, 3]
Используя ваш метод
df.drop(df.index[to_del])
A
1 1
4 4
1 6
4 9
Что является проблемой
Опция 1
использование np.in1d
найти дополнение to_del
Это более понятно, чем другие. Я ищу в массиве из 0
в n
и посмотреть, если это в to_del
, Результатом будет логический массив той же длины, что и df
, я использую ~
чтобы получить отрицание и использовать это, чтобы нарезать кадр данных.
df[~np.in1d(np.arange(len(df)), to_del)]
A
1 1
4 4
0 5
1 6
2 7
3 8
4 9
Вариант 2
использование np.bincount
найти дополнение to_del
Это выполняет то же самое, что и в варианте 1, путем подсчета позиций, определенных в to_del
, Я заканчиваю с массивом 0
а также 1
с 1
в каждой позиции, определенной в to_del
а также 0
еще где. Я хочу сохранить 0
s, поэтому я делаю логический массив, находя, где он равен 0
, Затем я использую это, чтобы разрезать фрейм данных.
df[np.bincount(to_del, minlength=len(df)) == 0]
A
1 1
4 4
0 5
1 6
2 7
3 8
4 9
Вариант 3
использование np.setdiff1d
найти позиции
При этом используется логика установки, чтобы найти разницу между полным массивом позиций и теми, которые я хочу удалить. Я тогда использую iloc
выбирать.
df.iloc[np.setdiff1d(np.arange(len(df)), to_del)]
A
1 1
4 4
0 5
1 6
2 7
3 8
4 9