как получить бесконечность python с хорошими свойствами [duplicate]

Вы можете свернуть свой собственный вариант Stream, обернув свою лямбда, чтобы выбросить исключенное исключение, а затем позже разблокировать это исключенное исключение в операциях терминала:

@FunctionalInterface
public interface ThrowingPredicate {
    public boolean test(T t) throws X;
}

@FunctionalInterface
public interface ThrowingFunction {
    public R apply(T t) throws X;
}

@FunctionalInterface
public interface ThrowingSupplier {
    public R get() throws X;
}

public interface ThrowingStream {
    public ThrowingStream filter(
            ThrowingPredicate predicate);

    public  ThrowingStream map(
            ThrowingFunction mapper);

    public  R collect(Collector collector) throws X;

    // etc
}

class StreamAdapter implements ThrowingStream {
    private static class AdapterException extends RuntimeException {
        public AdapterException(Throwable cause) {
            super(cause);
        }
    }

    private final Stream delegate;
    private final Class x;

    StreamAdapter(Stream delegate, Class x) {
        this.delegate = delegate;
        this.x = x;
    }

    private  R maskException(ThrowingSupplier method) {
        try {
            return method.get();
        } catch (Throwable t) {
            if (x.isInstance(t)) {
                throw new AdapterException(t);
            } else {
                throw t;
            }
        }
    }

    @Override
    public ThrowingStream filter(ThrowingPredicate predicate) {
        return new StreamAdapter<>(
                delegate.filter(t -> maskException(() -> predicate.test(t))), x);
    }

    @Override
    public  ThrowingStream map(ThrowingFunction mapper) {
        return new StreamAdapter<>(
                delegate.map(t -> maskException(() -> mapper.apply(t))), x);
    }

    private  R unmaskException(Supplier method) throws X {
        try {
            return method.get();
        } catch (AdapterException e) {
            throw x.cast(e.getCause());
        }
    }

    @Override
    public  R collect(Collector collector) throws X {
        return unmaskException(() -> delegate.collect(collector));
    }
}

. Тогда вы можете использовать это же точный способ как Stream:

Stream s = accounts.values().stream();
ThrowingStream ts = new StreamAdapter<>(s, IOException.class);
return ts.filter(Account::isActive).map(Account::getNumber).collect(toSet());

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

2
задан Mehrdad 10 December 2016 в 01:12
поделиться

4 ответа

Вот как подавить предупреждения:

mean, nanmean и warning: Среднее значение пустого среза

In [528]: import warnings

In [530]: x = np.array([0,1,2],float)
In [531]: y = np.array([np.inf,3,2],float)
In [532]: np.outer(x,y)
/usr/local/lib/python3.5/dist-packages/numpy/core/numeric.py:1093: RuntimeWarning: invalid value encountered in multiply
  return multiply(a.ravel()[:, newaxis], b.ravel()[newaxis,:], out)
Out[532]: 
array([[ nan,   0.,   0.],
       [ inf,   3.,   2.],
       [ inf,   6.,   4.]])

In [535]: with warnings.catch_warnings():
     ...:     warnings.simplefilter('ignore',category=RuntimeWarning)
     ...:     z = np.outer(x,y)
     ...:     
In [536]: z
Out[536]: 
array([[ nan,   0.,   0.],
       [ inf,   3.,   2.],
       [ inf,   6.,   4.]])

заменить nan на 1:

In [542]: z[np.isnan(z)]=1
In [543]: z
Out[543]: 
array([[  1.,   0.,   0.],
       [ inf,   3.,   2.],
       [ inf,   6.,   4.]])

In [547]: z[np.isinf(z)]=9999
In [548]: z
Out[548]: 
array([[  1.00000000e+00,   0.00000000e+00,   0.00000000e+00],
       [  9.99900000e+03,   3.00000000e+00,   2.00000000e+00],
       [  9.99900000e+03,   6.00000000e+00,   4.00000000e+00]])

===========================

Мы могли бы создать mask, используя тип тестирования что @P-robot демонстрирует:

In [570]: np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y))
Out[570]: 
array([[ True, False, False],
       [False, False, False],
       [False, False, False]], dtype=bool)
In [571]: mask=np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y))
In [572]: with warnings.catch_warnings():
     ...:     warnings.simplefilter('ignore',category=RuntimeWarning)
     ...:     z = np.outer(x,y)
     ...:     
In [573]: z[mask]=1
In [574]: z
Out[574]: 
array([[  1.,   0.,   0.],
       [ inf,   3.,   2.],
       [ inf,   6.,   4.]])

Или с более грязными входами:

In [587]: x = np.array([0,1,2,np.inf],float)
In [588]: y = np.array([np.inf,3,np.nan,0],float)
In [589]: mask=np.outer(np.isinf(x),y==0)|np.outer(x==0,np.isinf(y))
...
In [591]: with warnings.catch_warnings():
     ...:     warnings.simplefilter('ignore',category=RuntimeWarning)
     ...:     z = np.outer(x,y)
     ...:     
In [592]: z[mask]=1
In [593]: z
Out[593]: 
array([[  1.,   0.,  nan,   0.],
       [ inf,   3.,  nan,   0.],
       [ inf,   6.,  nan,   0.],
       [ inf,  inf,  nan,   1.]])
1
ответ дан Community 18 August 2018 в 10:57
поделиться
  • 1
    Это предполагает, что в любом входном массиве нет NaN, так? В противном случае вы можете замаскировать что-то. – Mehrdad 10 December 2016 в 02:21
  • 2
    Я добавил тест маскировки в соответствии с ответом @P-robot's. – hpaulj 10 December 2016 в 19:06

Одно из решений может заключаться в том, чтобы избежать использования np.multiply.outer и найти решение, используя умножение по типу на матрицах, которые уже были проверены, чтобы увидеть, соответствуют ли они интересующему условию (ноль в одном массиве, inf в другом массиве ).

import numpy as np
A = np.array([0., 0., 0.4, 2])
B = np.array([float('inf'), 1., 3.4, np.inf])

# Conditions of interest
c1 = (A == 0)
c2 = (B == np.inf)
condition1 = np.multiply.outer(c1, c2)
c3 = (A == np.inf)
c4 = (B == 0)
condition2 = np.multiply.outer(c3, c4)
condition = condition1 | condition2

AA = np.multiply.outer(A, np.ones(B.shape))
BB = np.multiply.outer(np.ones(A.shape), B)

AA[condition] = 0.
BB[condition] = 0.

AA*BB

Однако это может не соответствовать запросу «эффективности» плаката.

2
ответ дан p-robot 18 August 2018 в 10:57
поделиться
  • 1
    Eh ... +1, так как он все же лучше, чем цикл, но да, не то, на что я надеялся. – Mehrdad 10 December 2016 в 02:04
  • 2
    Да, я ценю, что это не самое элегантное (или эффективное) решение, но оно позволяет избежать подавления предупреждений. Приветствия. – p-robot 10 December 2016 в 19:11

Нужно ли беспокоиться о других источниках значений nan? Если нет, вы всегда можете просто исправить это на отдельном шаге:

import numpy as np

r = np.multiply.outer([0.], [float('inf')])
np.where(np.isnan(r), 0, r)

До вас, если вы хотите подавить предупреждения.

3
ответ дан ShadowRanger 18 August 2018 в 10:57
поделиться
  • 1
    Да, я все еще хочу получить нормальное поведение для других случаев. Но +1, поскольку это обходной путь для некоторых людей (хотя и очевидный). – Mehrdad 10 December 2016 в 01:58

Хотя я согласен с ответом @ ShadowRanger, дешевым взломом может воспользоваться np.nan_to_num , который заменяет infs большими конечными числами, которые затем передадут вам inf * 0 = 0.

Чтобы преобразовать ненужные оставшиеся высокие конечные числа обратно в inf (учитывая некоторые другие операции помимо вашего вопроса), вы можете использовать несколько больших чисел на что угодно> 1, а затем разделить на одну и ту же сумму (чтобы не влиять другие номера). Например:

In [1]: np.nan_to_num(np.inf)
Out[1]: 1.7976931348623157e+308

In [2]: np.nan_to_num(np.inf)*1.1
RuntimeWarning: overflow encountered in double_scalars
Out[2]: inf

In [3]: np.nan_to_num(np.inf)*1.1/1.1
RuntimeWarning: overflow encountered in double_scalars
Out[3]: inf

Перед потоком downvotes это явно не лучшая практика и потенциально может иметь побочные эффекты в зависимости от вашего варианта использования, но просто подумал, что я выбрал бы альтернативу.

0
ответ дан ZaxR 18 August 2018 в 10:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: