реорганизация записей в 2d массиве на основе определенных столбцов - PullRequest
2 голосов
/ 21 сентября 2019

Предположим, у меня есть массив M x N numpy, где каждая строка представляет запись данных, первые столбцы N-1 представляют различные параметры (независимая переменная), а последний столбец представляет данные, которые меня интересуют (зависимая переменная),

Какой самый элегантный способ перегруппировать различные строки так, чтобы они сортировались по параметрам?

Пример:

# original
1                        0.1                      20                       0.30000000000000004      0.07819319717404902     
1                        1                        10                       0.2                      0.07550707294415204      
2                        0.1                      0                        0                        0.07078663749666488      
2                        0.1                      0                        0.1                      0.07284943819285646      
1                        1                        15                       0.4                      0.08047398714777267      
1                        1                        15                       0.5                      0.0820402298018169      
1                        1                        15                       0.30000000000000004      0.07819319717406738     
1                        1                        20                       0                        0.07079655446543297      
1                        1                        20                       0.1                      0.07286704639139795      
1                        1                        5                        0.4                       0.086521872154



# desired:
1                        0.1                      20                       0.30000000000000004      0.07819319717404902     
1                        1                        5                        0.4                       0.086521872154
1                        1                        10                       0.2                      0.07550707294415204      
1                        1                        15                       0.30000000000000004      0.07819319717406738
1                        1                        15                       0.4                      0.08047398714777267      
1                        1                        15                       0.5                      0.0820402298018169      
1                        1                        20                       0                        0.07079655446543297      
1                        1                        20                       0.1                      0.07286704639139795      
2                        0.1                      0                        0                        0.07078663749666488      
2                        0.1                      0                        0.1                      0.07284943819285646 

Я хочу, чтобы данные сортировались по наименьшему в каждом параметре.

Ответы [ 3 ]

1 голос
/ 21 сентября 2019

Вы можете использовать lexsort:

original[np.lexsort(np.rot90(original))]
1 голос
/ 21 сентября 2019

Одна опция, которая использует pandas sort_values:

pd.DataFrame(a).sort_values(list(range(a.shape[1]))).values

Выход:

array([[ 1.        ,  0.1       , 20.        ,  0.3       ,  0.0781932 ],
       [ 1.        ,  1.        ,  5.        ,  0.4       ,  0.08652187],
       [ 1.        ,  1.        , 10.        ,  0.2       ,  0.07550707],
       [ 1.        ,  1.        , 15.        ,  0.3       ,  0.0781932 ],
       [ 1.        ,  1.        , 15.        ,  0.4       ,  0.08047399],
       [ 1.        ,  1.        , 15.        ,  0.5       ,  0.08204023],
       [ 1.        ,  1.        , 20.        ,  0.        ,  0.07079655],
       [ 1.        ,  1.        , 20.        ,  0.1       ,  0.07286705],
       [ 2.        ,  0.1       ,  0.        ,  0.        ,  0.07078664],
       [ 2.        ,  0.1       ,  0.        ,  0.1       ,  0.07284944]])
1 голос
/ 21 сентября 2019

Если вы хотите отсортировать ndarray по отдельным столбцам, используя np.argsort

Учитывая следующую матрицу:

m = np.array([[5., 0.1, 3.4],
           [7., 0.3, 6.8],
           [3., 0.2, 5.6]])

Этот код сортирует матрицу mна основе столбца 0:

m[m[:,0].argsort(kind='mergesort')]

Результат:

array([[3. , 0.2, 5.6],
       [5. , 0.1, 3.4],
       [7. , 0.3, 6.8]])

Если вы хотите отсортировать ndarray по нескольким столбцам, используя np.lexsort

Дано:

a = np.array([[1,20,200], [1,30,100], [1,10,300]])
array([[  1,  20, 200],
       [  1,  30, 100],
       [  1,  10, 300]])

Порядок по столбцу 1 и столбцу 0:

a[np.lexsort((a[:,0],a[:,1]))]
# output:
array([[  1,  10, 300],
       [  1,  20, 200],
       [  1,  30, 100]])

ПРИМЕЧАНИЕ : последний правый столбец (или строка, если keys - это двумерный массив) - первичный ключ сортировки.

Порядок по всем столбцам (начиная справа):

a[np.lexsort((a[:,0], a[:,1],a[:,2]))]
# output:
array([[  1,  30, 100],
       [  1,  20, 200],
       [  1,  10, 300]])

Или, что то же самое, порядок по всем столбцам без указаниястолбцы вручную (следуя порядку столбцов в матрице, начиная справа):

a[np.lexsort(list(map(tuple,np.column_stack(a))))]
# output:
array([[  1,  30, 100],
       [  1,  20, 200],
       [  1,  10, 300]])

Другой вариант: Панды - хорошая идея для вашей конкретной проблемы?

Другой вариант -переключиться на панд.Это работает, но это на порядок медленнее.Вот некоторые тесты на время выполнения:

Данные теста:

a = np.array([[1,20,200]*1000, [1,30,100]*1000, [1,10,300]*1000])

Версия Pandas:

%%timeit
pd.DataFrame(a).sort_values(list(range(a.shape[1]))).values
# 3.66 s ± 110 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Версия Numpy:

%%timeit
a[np.lexsort((a[:,0], a[:,1],a[:,2]))]
# 39.6 µs ± 12.1 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Как вы можете видеть, вы переходите от микросекунд numpy к секундам версии, основанной на пандах (примерно в 1 миллион раз медленнее).
Выбор за вами:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...