2016-08-30 4 views
2

У меня есть массивNumpy векторизованы нулевого порядка интерполяции

p = [[0.9, 0.95, 0.99], 
    [0.89, 0.94, 0.98], 
    [0.9, 0.95, 0.99], 
    [0.91, 0.96, 0.97], 
    ] 

и однородное случайное число для каждой строки

r = [0.5, 
    0.9, 
    0.3, 
    0.99] 

Я хочу знать, последний индекс столбца, где р равно еще меньше, чем г , т.е.

c = [0, 1, 0, 3] 

Для последнего случая значение не меньше. Если вы поместите столбец из 1s в конец p, это будет равно 3. Для меня также приемлема -1.

Наивное решение:

c = [] 
for prow, ri in zip(p, r): 
    ci = numpy.interp(ri, prow, arange(len(prow))) 
    c.append(int(numpy.ceil(ci))) 

print c 
[0, 1, 0, 3] 

Но я ищу vectorised решение, которое быстро и работает для больших массивов (миллионы строк, ~ 10 столбцов).

Я смотрел на эти решения:

  • scipy.interpolate.interp1d (вид = ноль)
    • это, кажется, требует внешнего цикла Python
  • г> р и NumPy . где
    • также, кажется, требует внешней петли питона
  • использованием numpy.random.choice

Для последнего я бы место (дифференциал) вероятностями вместо кумулятивных них:

p = [[0.9, 0.05, 0.04], 
    [0.89, 0.05, 0.04], 
    [0.9, 0.05, 0.04], 
    [0.91, 0.05, 0.01], 
    ] 

но numpy.random.choice не поддерживает векторизации (1, 2).

Is numpy.vectorise решение, или Cython? Я ищу быстрое решение.

+0

Я не сто процентов уверены, векторизации вполне разумно в этом контексте. Векторизация имеет смысл, если данные близки по памяти, что позволяет использовать SIMD. Это не обязательно здесь, то есть предположим, что для 1-й строки ваше состояние уже выполнено в 9-м столбце, тогда как для 2-й строки оно может быть выполнено только во втором столбце. Если вы придаете векторизованному коду приоритет, вы можете получить код, который делает ненужные двойные проверки, которые взамен будут стоить время выполнения. –

+0

@MohammedLi Как указано в вопросе '' миллионы строк, ~ 10 столбцов '', я думаю, что для вексеризованного решения будет уместна проблема. Во-первых, потому что он не будет итерировать на уровне python для такого огромного количества строк, а во-вторых, из-за ограниченного количества cols, он не будет слишком сильно блуждать по любой строке. – Divakar

+0

@wwii Глядя на ожидаемое решение, я интерпретировал это как «индекс первого столбца, где p больше r». ОП вы могли бы прояснить это? – Divakar

ответ

3

Вот один Векторизованное решения с использованием broadcasting -

mask = (p > r[:,None]) 
out = np.where(mask.any(1),mask.argmax(1),p.shape[1]) 

Sample пробега -

In [50]: p 
Out[50]: 
array([[ 0.9 , 0.95, 0.99], 
     [ 0.89, 0.94, 0.98], 
     [ 0.9 , 0.95, 0.99], 
     [ 0.91, 0.96, 0.97]]) 

In [51]: r 
Out[51]: array([ 0.5 , 0.9 , 0.3 , 0.99]) 

In [52]: mask = (p > r[:,None]) # 2D Mask of row-wise comparisons 

In [53]: mask 
Out[53]: 
array([[ True, True, True], 
     [False, True, True], 
     [ True, True, True], 
     [False, False, False]], dtype=bool) 

In [54]: np.where(mask.any(1),mask.argmax(1),p.shape[1]) 
Out[54]: array([0, 1, 0, 3]) 
Смежные вопросы