Подтвердить что ты не робот

Функция-приложение по матричной строке/столбцу

Я использую Numpy для хранения данных в матрицах. Исходя из R-фона, был чрезвычайно простой способ применения функции по строкам/столбцам или обеим матрицам.

Есть ли что-то подобное для комбинации python/numpy? Это не проблема для написания моей небольшой реализации, но мне кажется, что большинство версий, которые я придумал, будут значительно менее эффективными/интенсивнее, чем любая из существующих реализаций.

Я бы хотел избежать копирования из матрицы numpy в локальную переменную и т.д., возможно ли это?

Функции, которые я пытаюсь реализовать, - это в основном простые сравнения (например, сколько элементов определенного столбца меньше числа x или сколько из них имеют абсолютное значение, большее y).

4b9b3361

Ответ 1

Почти все функции numpy работают на целых массивах и/или могут использоваться для работы на определенной оси (строка или столбец).

Пока вы можете определить свою функцию с точки зрения функций numpy, действующих на массивах numpy или массивах, ваша функция будет автоматически работать со всеми массивами, строками или столбцами.

Может быть более полезно спросить о том, как реализовать конкретную функцию, чтобы получить более конкретные советы.


Numpy предоставляет np.vectorize и np.frompyfunc, чтобы включить функции Python, которые работают с числами в функции которые работают с массивами numpy.

Например,

def myfunc(a,b):
    if (a>b): return a
    else: return b
vecfunc = np.vectorize(myfunc)
result=vecfunc([[1,2,3],[5,6,9]],[7,4,5])
print(result)
# [[7 4 5]
#  [7 6 9]]

(Элементы первого массива заменяются соответствующим элементом второго массива, когда второй больше.)

Но не слишком волнуйтесь; np.vectorize и np.frompyfunc являются просто синтаксическим сахаром. На самом деле они не делают ваш код быстрее. Если ваша базовая функция Python работает по одному значению за раз, то np.vectorize будет подавать по одному элементу за раз, а целое операция будет довольно медленной (по сравнению с использованием функции numpy, которая вызывает некоторую базовую реализацию C или Fortran).


Чтобы подсчитать, сколько элементов столбца x меньше числа y, вы можете использовать выражение, например:

(array['x']<y).sum()

Например:

import numpy as np
array=np.arange(6).view([('x',np.int),('y',np.int)])
print(array)
# [(0, 1) (2, 3) (4, 5)]

print(array['x'])
# [0 2 4]

print(array['x']<3)
# [ True  True False]

print((array['x']<3).sum())
# 2

Ответ 2

Выбор элементов из массива NumPy на основе одного или нескольких условий является простым использованием красивого синтаксиса NumPy:

>>> import numpy as NP
>>> # generate a matrix to demo the code
>>> A = NP.random.randint(0, 10, 40).reshape(8, 5)
>>> A
  array([[6, 7, 6, 4, 8],
         [7, 3, 7, 9, 9],
         [4, 2, 5, 9, 8],
         [3, 8, 2, 6, 3],
         [2, 1, 8, 0, 0],
         [8, 3, 9, 4, 8],
         [3, 3, 9, 8, 4],
         [5, 4, 8, 3, 0]])


, сколько элементов в столбце 2 больше 6?

>>> ndx = A[:,1] > 6
>>> ndx
      array([False,  True, False, False,  True,  True,  True,  True], dtype=bool)
>>> NP.sum(ndx)
      5


, сколько элементов в последнем столбце A имеют абсолютное значение больше 3?

>>> A = NP.random.randint(-4, 4, 40).reshape(8, 5)
>>> A
  array([[-4, -1,  2,  0,  3],
         [-4, -1, -1, -1,  1],
         [-1, -2,  2, -2,  3],
         [ 1, -4, -1,  0,  0],
         [-4,  3, -3,  3, -1],
         [ 3,  0, -4, -1, -3],
         [ 3, -4,  0, -3, -2],
         [ 3, -4, -4, -4,  1]])

>>> ndx = NP.abs(A[:,-1]) > 3
>>> NP.sum(ndx)
      0


, сколько элементов в первых двух строках A больше или равно 2?

>>> ndx = A[:2,:] >= 2
>>> NP.sum(ndx.ravel())    # 'ravel' just flattens ndx, which is originally 2D (2x5)
      2

Синтаксис индексации NumPy довольно близок к R; учитывая вашу беглость в R, вот основные различия между R и NumPy в этом контексте:

NumPy индексы основаны на нулевом значении, в R индексирование начинается с 1

NumPy (например, Python) позволяет индексировать справа налево с использованием отрицательных индексов - например,

# to get the last column in A
A[:, -1], 

# to get the penultimate column in A
A[:, -2] 

# this is a big deal, because in R, the equivalent expresson is:
A[, dim(A)[0]-2]

NumPy использует двоеточие ":" обозначение, обозначающее "unsliced" , например, в R, для  возьмите первые три строки в A, вы будете использовать A [1: 3,]. В NumPy вы  будет использовать A [0: 2,:] (в NumPy "0" не требуется, на самом деле это  предпочтительно использовать A [: 2,:]

Ответ 3

Я также пришел из более R-фона и столкнулся с отсутствием более универсального применения, которое может выполнять короткие настраиваемые функции. Я видел форумы, предлагающие использовать основные функции numpy, потому что многие из них обрабатывают массивы. Тем не менее, я запутался в том, что "родные" функции numpy обрабатывают массив (иногда 0 - по строкам и по 1 столбцу, иногда наоборот).

Мое личное решение для более гибких функций с применением apply_along_axis состояло в том, чтобы объединить их с неявными лямбда-функциями, доступными в python. Лямбда-функции должны очень легко понять для единомышленников, которые используют более функциональный стиль программирования, например, в функциях R, sapply, lapply и т.д.

Так, например, я хотел применить стандартизацию переменных в матрице. Tipically в R есть функция для этого (шкала), но вы также можете легко ее создать с помощью:

(код R)

apply(Mat,2,function(x) (x-mean(x))/sd(x) ) 

Вы видите, как применяется тело внутри функции (x-mean (x))/sd (x) - это бит, который мы не можем вводить непосредственно для python apply_along_axis. С лямбдой это легко осуществить ДЛЯ ОДНОГО НАСТРОЙКИ ЗНАЧЕНИЙ, так:

(Python)

import numpy as np
vec=np.random.randint(1,10,10)  # some random data vector of integers

(lambda x: (x-np.mean(x))/np.std(x)  )(vec)

Затем нам нужно только подключить это внутри приложения python и передать массив интересов с помощью apply_along_axis

Mat=np.random.randint(1,10,3*4).reshape((3,4))  # some random data vector
np.apply_along_axis(lambda x: (x-np.mean(x))/np.std(x),0,Mat )

Очевидно, что лямбда-функция может быть реализована как отдельная функция, но я думаю, что все дело в том, чтобы использовать довольно мелкие функции, содержащиеся в строке, в которой применяется запрос.

Надеюсь, вы сочтете это полезным!