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

#python #pandas

Вопрос:

У меня есть фрейм данных pandas, который содержит только числа.

Я хочу получить список (row_index, column_index) всех ячеек со значением >= 1.

Я написал вложенный цикл for, но на самом деле он очень медленный.

 res= []
for i in range (df.shape[0]):
    for j in range (i 1, df.shape[0]):
        if df.iloc[i,j] >= 1:
            res.append ([i,j,df.iloc[i,j]])
 

Есть ли более быстрый способ выполнить эту задачу? Матрица симметрична, поэтому я рассматриваю только половину кадра данных.

Фрейм данных:

 1 2 0
0 0 1
0 1 0
 

Ожидаемый результат:

 0 0 1
0 1 2
1 2 1
2 1 1
 

Первая строка ожидаемого выхода (0 0 1) означает, что в строке 0, столбце 0 значение ячейки >= 1 и равно 1.

Комментарии:

1. пожалуйста, поделитесь фреймом данных с ожидаемым результатом

Ответ №1:

Мне нравится query :

 df = df.rename_axis(index='idx', columns='cols')
df.stack().reset_index(name='value').query('value >= 1')
 

Выход:

    idx  cols  value
0    0     0      1
1    0     1      2
5    1     2      1
7    2     1      1
 

rename_axis Затем используйте для обработки некоторых имен столбцов очистки stack reset_index и фильтрации query с помощью фрейма данных .

Ответ №2:

Затем мы можем использовать stack фильтр для значений ge 1:

 output = (
    df.stack()
        .loc[lambda f: f.ge(1)]
        .rename_axis(['index', 'column'])
        .reset_index(name='value')
)
 

output :

    index  column  value
0      0       0      1
1      0       1      2
2      1       2      1
3      2       1      1
 

stack изменяет форму фрейма данных, чтобы столбцы и индексы строк располагались в строках:

 output = df.stack()
 
 0  0    1
   1    2
   2    0
1  0    0
   1    0
   2    1
2  0    0
   1    1
   2    0
dtype: int64
 

loc может использоваться для цепных фильтров:

 output = df.stack().loc[lambda f: f.ge(1)]
 

Это также можно было бы сделать в 2 этапа:

 output = df.stack()
output = output[output.ge(1)]
 
 0  0    1
   1    2
1  2    1
2  1    1
dtype: int64
 

rename_axis чтобы добавить метки в мультииндекс:

 output = (
    df.stack()
        .loc[lambda f: f.ge(1)]
        .rename_axis(['index', 'column'])
)
 
 index  column
0      0          1
       1          2
1      2          1
2      1          1
dtype: int64
 

Затем reset_index , чтобы превратить мультииндекс в столбцы:

 output = (
    df.stack()
        .loc[lambda f: f.ge(1)]
        .rename_axis(['index', 'columns'])
        .reset_index(name='value')
)
 

Или

 output = df.stack()
output = output[output.ge(1)].rename_axis(['index', 'columns']).reset_index()
 
    index  column  value
0      0       0      1
1      0       1      2
2      1       2      1
3      2       1      1
 

Ответ №3:

Другой путь через melt() sort_values() :

 out=(df.reset_index()
       .melt('index',var_name='column')
       .query('value>=1')
       .sort_values('index'))
 

выход из out :

   index     column  value
0   0       0       1
3   0       1       2
7   1       2       1
5   2       1       1
 

Используемый образец фрейма данных:

 df=pd.DataFrame(np.array([[1,2,0],[0,0,1],[0,1,0]]))