Как эффективно фильтровать фрейм данных, когда мне нужно сравнивать значения двух столбцов?

#python #pandas #performance #dataframe #filter

#python #pandas #Производительность #фрейм данных #Фильтр

Вопрос:

на данный момент я работаю над проектом и столкнулся с некоторой проблемой эффективности. В какой-то момент у меня огромный фрейм данных, и мне нужно удалить строки. Мой фрейм данных содержит два столбца, где значение равно либо ‘0’, ‘1’, либо другому np.nan.

Мне нужно удалить все строки, где первый столбец равен «0», а другой — «1» или наоборот. Я хочу сохранить все остальные комбинации.

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

 data = {'val': ['a', 'b', 'c'],
         'compare1': ['0', '0', '1'],
        'compare2': ['0', None,  '0']
        }

df = pd.DataFrame (data)
df

>       val     compare1    compare2
>  0    a       0           0
>  1    b       0           None
>  2    c       1           0
  

моя функция:

 def filter_df(df, colname1, colname2):
    for index, row in df.iterrows():
        if (row[colname1] == "0") and (row[colname2] == "1"):
            df.drop(index, inplace=True)
        if (row[colname1] == "1") and (row[colname2] == "0"):
            df.drop(index, inplace=True)
    return df
  

результат, который я хочу иметь и получать с помощью fkt:

 df_new = filter_df(df,'compare1', 'compare2')
df_new

>       val     compare1    compare2
>  0    a       0           0
>  1    b       0           None
  

Если у вас есть идея сделать его более эффективным, пожалуйста, дайте мне знать :-). Я очень рад любой помощи.

Лучший P

Ответ №1:

вы можете использовать такие условия:

 mask1 = ~((df['compare1'] == "0") amp; (df['compare2'] == "1")) 
mask2 = ~((df['compare1'] == "1") amp; (df['compare2'] == "0"))
df = df[mask1 amp; mask2 ]
  

если производительность по-прежнему неэффективна для вас, я бы посоветовал вам перейти на numpy для повышения производительности…

Ответ №2:

Вы можете преобразовать фрейм данных в числовые типы :

 df = df.transform(pd.to_numeric, errors="ignore")
df


  val   compare1    compare2
0   a      0        0.0
1   b      0        NaN
2   c      1        0.0
  

Затем фильтруйте, где сумма compare столбцов равна 1 :

 df.loc[~df.compare1.add(df.compare2).eq(1)]


   val  compare1    compare2
0   a       0       0.0
1   b       0       NaN