#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]]))