Numpy: рдЕрджреНрд╡рд┐рддреАрдп рдФрд░ NaN рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдБ (Trac # 1514)

рдХреЛ рдирд┐рд░реНрдорд┐рдд 19 рдЕрдХреНрддреВре░ 2012  ┬╖  14рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: numpy/numpy

_рдСрд░рд┐рдЬрд┐рдирд▓ рдЯрд┐рдХрдЯ http://projects.scipy.org/numpy/ticket/1514 2010-06-18 рдХреЛ trac рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ rspringuel рджреНрд╡рд╛рд░рд╛, рдЕрдЬреНрдЮрд╛рдд рдХреЛ рд╕реМрдВрдкрд╛ рдЧрдпрд╛ ред_

рдЬрдм рдХрдИ NaN рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╕рд░рдгреА рдкрд░ рдЕрджреНрд╡рд┐рддреАрдп рд╕рдВрдЪрд╛рд▓рд┐рдд рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХреА рд╡рд╛рдкрд╕реА рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдХреЗ рд▓рд┐рдП рдПрдХ NaN рд╢рд╛рдорд┐рд▓ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рдореВрд▓ рд╕рд░рдгреА рдореЗрдВ NaN рдерд╛ред

рдЙрджрд╛рд╣рд░рдг:
a = random.randint (5, рдЖрдХрд╛рд░ = 100)ред рдкреНрд░рд╛рд░реВрдк (рдлреНрд▓реЛрдЯ)

[[резреи] = рдиреИрди # рдПрдХ рдПрдХрд▓ рдиреЗрди рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐
рдЕрджреНрд╡рд┐рддреАрдп (рдХ)
рд╕рд░рдгреА ([0., 1., 2., 3., 4., NaN])
[[реиреж] = рдирд╛рди # рдП рдбреА рдП рдбреА
рдЕрджреНрд╡рд┐рддреАрдп (рдХ)
рд╕рд░рдгреА ([0., 1., 2., 3., 4., NaN, NaN])
[резрей] = рдирд╛рди
рдЕрджреНрд╡рд┐рддреАрдп (рдП) # рдФрд░ рдПрдХ рддрд┐рд╣рд╛рдИ
рд╕рд░рдгреА ([0., 1., 2., 3., 4., NaN, NaN, NaN])

рдпрд╣ рд╢рд╛рдпрдж рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рд╣реИ рдХрд┐ x == y рдЧрд▓рдд рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ x рдФрд░ y рджреЛрдиреЛрдВ NaN рд╣реИрдВред рдкрд╣рд▓реЗ рд╕реЗ рдкрд╣рдЪрд╛рдиреЗ рдЧрдП рдорд╛рдиреЛрдВ рдореЗрдВ рдорд╛рди рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХрд░рдиреЗ рд╡рд╛рд▓реА рд╕рд╢рд░реНрдд рдЬреЛрдбрд╝реА рдореЗрдВ "рдпрд╛ (isnan (x) рдФрд░ isnan (y))" рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореБрдЭреЗ рдирд╣реАрдВ рдкрддрд╛ рдерд╛ рдХрд┐ рдореИрдВ рдЕрджреНрд╡рд┐рддреАрдп рдЬреАрд╡рди рдЬреА рд░рд╣рд╛ рдерд╛ рдФрд░ рдЬрдм рдореИрдВ рджреЗрдЦ рд░рд╣рд╛ рдерд╛ рддреЛ рдЙрд╕реЗ рдирд╣реАрдВ рдкрд╛ рд╕рдХрд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЦреБрдж рдмрджрд▓рд╛рд╡ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ (рдпрд╛ рдпрд╣ рднреА рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реВрдВ рдХрд┐ рд╕рд╢рд░реНрдд рдХрд╛ рд╕рдЯреАрдХ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреНрдпрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП)ред

рд╕рд╛рде рд╣реА, рд╡реНрдпрд╡рд╣рд╛рд░ рдкрд░ рдкреИрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрди рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдбреАрдПрди рдиреЗрдиреБрдиреАрдХ (x):
a = numpy.unique (x)
рдЖрд░ = []
рдореЗрдВ рдореИрдВ рдХреЗ рд▓рд┐рдП рдПрдХ:
рдЕрдЧрд░ рдореИрдВ r рдпрд╛ (numpy.isnan (i) рдФрд░ numpy.any (numpy.isnan (r))):
рдЬрд╛рд░реА рд░рдЦреЗрдВ
рдЕрдиреНрдп:
r.append (i)
рд╡рд╛рдкрд╕реА numpy.array (рдЖрд░)

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдореИрдВ рдЖрдЬ рдЙрд╕реА рдореБрджреНрджреЗ рдкрд░ рднрд╛рдЧрд╛ред Np.unique рд░реВрдЯреАрди рдХрд╛ рдореВрд▓, рдорд╛рдиреЛрдВ рдХреЛ рдЙрд╕ рд╕реЙрд░реНрдЯ рдХрд┐рдП рдЧрдП рд╕рд░рдгреА рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛрдиреЗ рдкрд░ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдЦреНрдпрд╛рддреНрдордХ / lib / arraysetops.py рдореЗрдВ рдПрдХ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рд╕реЙрд░реНрдЯ рдХрд┐рдП рдЧрдП рд╕рд░рдгреА рдкрд░ рдПрдХ рдорд╛рд╕реНрдХ рдХреА рдЧрдгрдирд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ:

mask = np.empty(aux.shape, dtype=np.bool_)
mask[:1] = True
mask[1:] = aux[1:] != aux[:-1]

рдЗрд╕реЗ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рд▓рдЧрднрдЧ 5 рд╕рд╛рд▓ рдкрд╣рд▓реЗ рд╕реЗ jaimefrio рдХреА рдЯрд┐рдкреНрдкрдгреА рдХреА рддрд░реНрдЬ рдкрд░ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ argmin рдХреЙрд▓ рд╕реЗ рдмрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ:

mask = np.empty(aux.shape, dtype=np.bool_)
mask[:1] = True
if (aux.shape[0] > 0 and isinstance(aux[-1], (float, np.float16,
                                              np.float32, np.float64))
    and np.isnan(aux[-1])):
    aux_firstnan = np.searchsorted(aux, np.nan, side='left')
    mask[1:aux_firstnan] = (aux[1:aux_firstnan] != aux[:aux_firstnan-1])
    mask[aux_firstnan] = True
    mask[aux_firstnan+1:] = False
else:
    mask[1:] = aux[1:] != aux[:-1]

рдХреБрдЫ% timeit рдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдкрд░ рдореИрдВрдиреЗ рдЕрдзрд┐рдХрддрдо <10% рд░рдирдЯрд╛рдЗрдо рдкреЗрдирд▓реНрдЯреА рдХрд╛ рдЕрд╡рд▓реЛрдХрди рдХрд┐рдпрд╛ рдпрджрд┐ рд╕рд░рдгреА рдмрдбрд╝реА рд╣реИ рдФрд░ рдмрд╣реБрдд рдХрдо NaN рд╣реИрдВ (1 рдорд┐рд▓рд┐рдпрди рдореЗрдВ рд╕реЗ 10 NaN рдХрд╣рддреЗ рд╣реИрдВ), рдФрд░ рдРрд╕реЗ рдмрдбрд╝реЗ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рддреЗрдЬреА рд╕реЗ рдЪрд▓рддрд╛ рд╣реИ рдЕрдЧрд░ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╣реИрдВ NaN рдХреЗред

рджреВрд╕рд░реА рдУрд░, рдпрджрд┐ рд╕рд░рдгрд┐рдпрд╛рдБ рдЫреЛрдЯреА рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 10 рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдБ) рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкреНрд░рджрд░реНрд╢рди рд╣рд┐рдЯ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдлреНрд▓реЛрдЯ рдФрд░ NaN рдХреЗ рд▓рд┐рдП рдЪреЗрдХ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдорд╣рдВрдЧрд╛ рд╣реИ, рдФрд░ рд░рдирдЯрд╛рдЗрдо рдХрдИ рддрдХ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рддрдм рднреА рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ рдпрджрд┐ рдХреЛрдИ NaN рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЬрд╛рдВрдЪ рд╣реИ рдЬреЛ рдзреАрдореА рд╣реИред

рдпрджрд┐ рд╕рд░рдгреА рдореЗрдВ NaN рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдпрд╣ NaNs рдХреЗ рд╕рдВрдпреЛрдЬрди рд╕реЗ рдПрдХ рдЕрд▓рдЧ рдкрд░рд┐рдгрд╛рдо рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдпрд╣ рд╕рдм рд╣реИред рддреЛ рдЙрд╕ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рд╕рд╡рд╛рд▓ рд╣реИ (рд╕рднреА NaN рдПрдХ рдПрдХрд▓ рдореВрд▓реНрдп рд╕рдореВрд╣ рдореЗрдВ рд╕рдВрдпреБрдХреНрдд) рдереЛрдбрд╝рд╛ рдзреАрдорд╛ рдмрдирд╛рдо рдПрдХ рдЕрд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ (рдкреНрд░рддреНрдпреЗрдХ NaN рдЕрдкрдиреЗ рдореВрд▓реНрдп рд╕рдореВрд╣ рдореЗрдВ) рдереЛрдбрд╝рд╛ рддреЗрдЬред

рдЕрдВрдд рдореЗрдВ, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рдкреИрдЪ NaNs рдпреБрдХреНрдд рдпреМрдЧрд┐рдХ рд╡рд╕реНрддреБрдУрдВ рдЬреИрд╕реЗ рдЕрджреНрд╡рд┐рддреАрдп рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдореЗрдВ рдареАрдХ рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдЬреИрд╕реЗ рдХрд┐ рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ:

a = np.array([[0,1],[np.nan, 1], [np.nan, 1]])
np.unique(a, axis=0)

рдЬреЛ рдЕрднреА рднреА рд▓реМрдЯреЗрдЧрд╛

array([[ 0.,  1.],
       [nan,  1.],
       [nan,  1.]])

рд╕рднреА 14 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

_trac рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ rspringuel рдиреЗ 2010-06-18_ рдкрд░ рд▓рд┐рдЦрд╛

рдКрдкрд░ рджрд┐рдП рдЧрдП рдХреЛрдб рдмреНрд▓реЙрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╢реВрдЯ рдХрд░реЗрдВред рдпрд╣ рдХреЗрд╡рд▓ рдкреИрдЪ-рдУрд╡рд░ рдХреЛрдб рдХреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЗрд╕реЗ рдХреЗрд╡рд▓ рд░реАрдкреЛрд╕реНрдЯ рдХрд░реВрдВрдЧрд╛:

def nanunique(x):
    a = numpy.unique(x)
    r = []
    for i in a:
        if i in r or (numpy.isnan(i) and numpy.any(numpy.isnan(r))):
            continue
        else:
            r.append(i)
    return numpy.array(r)

рдлрд┐рдХреНрд╕реНрдбред

рдореИрдВ рдЕрднреА рднреА рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдирд╡реАрдирддрдо рдорд╛рд╕реНрдЯрд░ рдХреЗ рд╕рд╛рде рджреЗрдЦ рд░рд╣рд╛ рд╣реВрдВред рдЗрд╕реЗ рдХрд┐рд╕ рдХрдореЗрдЯреА рдХреЛ рддрдп рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдерд╛? рдЬрдм рддрдХ рдореБрдЭреЗ рдХреБрдЫ рдпрд╛рдж рдирд╣реАрдВ рдЖ рд░рд╣рд╛ рд╣реИ рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдлрд┐рд░ рд╕реЗ рдЦреЛрд▓рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреВрдВрдЧрд╛ред

рдпрд╣ рдлрд╝реНрд▓реЛрдЯреНрд╕ рдХреЗ рд▓рд┐рдП рдареАрдХ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЬрдЯрд┐рд▓ рдпрд╛ рд╕рдВрд░рдЪрд┐рдд dtypes рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╕рд╛рди рд░рд╛рд╕реНрддрд╛ рдирд╣реАрдВ рджрд┐рдЦрддрд╛ рд╣реИред рдПрдХ рд╕рд╛рде рдПрдХ рддреНрд╡рд░рд┐рдд рдкреАрдЖрд░ рдбрд╛рд▓ рджреЗрдВрдЧреЗ рдФрд░ рд╣рдо рд╡рд╣рд╛рдБ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

@jaimefrio рдореИрдВ рдпрд╣ рдЕрджреНрд╡рд┐рддреАрдп рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рддрдп рдХрд┐рдпрд╛ рд╣реИ

    if issubclass(aux.dtype.type, np.inexact):
        # nans always compare unequal, so encode as integers
        tmp = aux.searchsorted(aux)
    else:
        tmp = aux
    flag = np.concatenate(([True], tmp[1:] != tmp[:-1]))

рд▓реЗрдХрд┐рди рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдиреНрдп рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рднреА рд╕рдорд╕реНрдпрд╛рдПрдВ рд╣реИрдВред рд╢рд╛рдпрдж рд╣рдореЗрдВ nan_equal, nan_not_equal ufuncs, рдпрд╛ рд╢рд╛рдпрдж nanfuntions рдореЗрдВ рдХреБрдЫ рдЪрд╛рд╣рд┐рдПред

Sortsearching aux рдЕрдкрдиреЗ рд▓рд┐рдП рдПрдХ рд╕реНрдорд╛рд░реНрдЯ рдЯреНрд░рд┐рдХ рд╣реИ! рд╣рд╛рд▓рд╛рдБрдХрд┐ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рдХрд┐ рдЗрд╕рдореЗрдВ рд╕реЗ _all_ рдереЛрдбрд╝рд╛ рдмреЗрдХрд╛рд░ рд╣реИ, рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ рд╣рдо рдкрд╣рд▓реА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдХреЛ рдПрдХ рдиреИрдиреЛ рдХреЗ рд╕рд╛рде рд░рдЦрдирд╛ рдЪрд╛рд╣реЗрдВрдЧреЗ, рд╢рд╛рдпрдж рдХреБрдЫ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде, aux рдФрд░ flag рд░реВрдк рдореЗрдВ рд╕рд╣реА рд╣реЛрдиреЗ рдХреЗ рдмрд╛рдж, рдЕрднреА рдХрд░ рд░рд╣реЗ рд╣реИрдВ :

if not aux[-1] == aux[-1]:
    nanidx = np.argmin(aux == aux)
    nanaux = aux[nanidx:].searchsorted(aux[nanidx:])
    flag[nanidx+1:] = nanaux[1:] != nanaux[:-1]

рдпрд╛ рдХреБрдЫ рдПрдХ рдХреЗ рдмрд╛рдж рдПрдХ рдмрдВрдж рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рд╣реА рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рднреА рдРрд╕рд╛ рд╣реА рдХреБрдЫ рд╣реИ рдЬреЛ рдореИрдВрдиреЗ рд╡рд╣рд╛рдБ рдкреЗрд╢ рдХрд┐рдпрд╛ рд╣реИред

рдореЗрд░рд╛ рдпрд╣ рдЕрдВрддрд┐рдо рддрд░реАрдХрд╛ рдлреНрд▓реЛрдЯ рдФрд░ рдЬрдЯрд┐рд▓ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧрд╛, рд▓реЗрдХрд┐рди рдлреНрд▓реЛрдЯрд┐рдВрдЧ рдкреЙрдЗрдВрдЯ рдлрд╝реАрд▓реНрдб рдХреЗ рд╕рд╛рде рд╕рдВрд░рдЪрд┐рдд dtypes рдХреЗ рд▓рд┐рдП рдЕрд╕рдлрд▓ред рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдЕрднреА рднреА рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЦреЛрдЬ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдЯреНрд░рд┐рдХ, рднрд▓реЗ рд╣реА рдпрд╣ рд╕рднреА рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧреА, рдмрд╣реБрдд рдмреЗрдХрд╛рд░ рд╣реИред рдХреБрдЫ рд╕рдордп:

In [10]: a = np.random.randn(1000)

In [11]: %timeit np.unique(a)
10000 loops, best of 3: 69.5 us per loop

In [12]: b = np.sort(a)

In [13]: %timeit b.searchsorted(b)
10000 loops, best of 3: 28.1 us per loop

рдпрд╣ рдПрдХ 40% рдкреНрд░рджрд░реНрд╢рди рд╣рд┐рдЯ рд╣реЛрдиреЗ рд╡рд╛рд▓рд╛ рд╣реИ, рдЬреЛ nanunique рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдареАрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдВрднрд╡рддрдГ рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВред

2019 рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдУрдкреА рд╕рдорд╕реНрдпрд╛ рдЕрднреА рднреА рд╡реИрдз рд╣реИ рдФрд░ рдХреЛрдб рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдкреНрд░рд╕реНрддреБрдд рдХрд░рдиреЗ рдпреЛрдЧреНрдп рд╣реИред

@jaimefrio рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЧрд▓рдд рд╣реЛрдиреЗ рдХрд╛ рд╡рд┐рдХрд▓реНрдк рдХреНрдпреЛрдВ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ?

рдореЗрд░рд╛ рдорддрд▓рдм рд╣реИ, рдпрд╣ рд╡реНрдпрд╡рд╣рд╛рд░ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рднреНрд░рдорд┐рдд рдХрд░ рд░рд╣рд╛ рд╣реИ, рдФрд░ рдкреНрд░рджрд░реНрд╢рди рдХреЛрдИ рдмрд╣рд╛рдирд╛ рдирд╣реАрдВ рд╣реИред

@ Demetrio92 рдЬрдмрдХрд┐ рдореИрдВ рдЗрд╕ рдореБрджреНрджреЗ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рдиреЗ рдХреЗ рдЖрдкрдХреЗ рдкреНрд░рдпрд╛рд╕ рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХрд░рддрд╛ рд╣реВрдВ, рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рд╡рд┐рдбрдВрдмрдирд╛ / рдХрдЯрд╛рдХреНрд╖ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд▓реЛрдЧреЛрдВ рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЗ рд╕реЗ рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ, рдХреГрдкрдпрд╛ рдЗрд╕реЗ рдмрдирд╛рдП рд░рдЦреЗрдВред рд╣рдо рдореЗрдВ рд╕реЗ рдХреБрдЫ рдХреЗ рд▓рд┐рдП, рдкреНрд░рджрд░реНрд╢рди рдмрд╣реБрдд рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рдФрд░ рд╣рдо рд▓рд╛рдкрд░рд╡рд╛рд╣реА рд╕реЗ рдХреЛрдб рдирд╣реАрдВ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдЬреЛ рдЪреАрдЬреЛрдВ рдХреЛ рдзреАрдорд╛ рдХрд░ рджреЗрддрд╛ рд╣реИред

PR # 5487 рдЯрд┐рдкреНрдкрдгреА рдХрд░рдиреЗ рдпрд╛ рдЖрдЧреЗ рдмрдврд╝рдиреЗ рдХреЗ рд╕реБрдЭрд╛рд╡ рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмреЗрд╣рддрд░ рд╕реНрдерд╛рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред

рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ: PR рдирдВрдмрд░ рдареАрдХ рдХрд░реЗрдВ

рдпрд╣ рд╕рдорд╕реНрдпрд╛ 8 рд╕рд╛рд▓ рд╕реЗ рдЦреБрд▓реА рд╣реБрдИ рдкреНрд░рддреАрдд рд╣реЛ рд░рд╣реА рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВ рд╕рд┐рд░реНрдл numpy.unique рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП +1 рдХреЗ рд╕рд╛рде рдЭрдВрдХрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХреНрдпреЛрдВрдХрд┐

рдореИрдВ рдЖрдЬ рдЙрд╕реА рдореБрджреНрджреЗ рдкрд░ рднрд╛рдЧрд╛ред Np.unique рд░реВрдЯреАрди рдХрд╛ рдореВрд▓, рдорд╛рдиреЛрдВ рдХреЛ рдЙрд╕ рд╕реЙрд░реНрдЯ рдХрд┐рдП рдЧрдП рд╕рд░рдгреА рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╣реЛрдиреЗ рдкрд░ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдЦреНрдпрд╛рддреНрдордХ / lib / arraysetops.py рдореЗрдВ рдПрдХ рдЕрдирд┐рдпрдВрддреНрд░рд┐рдд рд╕реЙрд░реНрдЯ рдХрд┐рдП рдЧрдП рд╕рд░рдгреА рдкрд░ рдПрдХ рдорд╛рд╕реНрдХ рдХреА рдЧрдгрдирд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ:

mask = np.empty(aux.shape, dtype=np.bool_)
mask[:1] = True
mask[1:] = aux[1:] != aux[:-1]

рдЗрд╕реЗ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рд▓рдЧрднрдЧ 5 рд╕рд╛рд▓ рдкрд╣рд▓реЗ рд╕реЗ jaimefrio рдХреА рдЯрд┐рдкреНрдкрдгреА рдХреА рддрд░реНрдЬ рдкрд░ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕ argmin рдХреЙрд▓ рд╕реЗ рдмрдЪрд╛ рдЬрд╛рддрд╛ рд╣реИ:

mask = np.empty(aux.shape, dtype=np.bool_)
mask[:1] = True
if (aux.shape[0] > 0 and isinstance(aux[-1], (float, np.float16,
                                              np.float32, np.float64))
    and np.isnan(aux[-1])):
    aux_firstnan = np.searchsorted(aux, np.nan, side='left')
    mask[1:aux_firstnan] = (aux[1:aux_firstnan] != aux[:aux_firstnan-1])
    mask[aux_firstnan] = True
    mask[aux_firstnan+1:] = False
else:
    mask[1:] = aux[1:] != aux[:-1]

рдХреБрдЫ% timeit рдкреНрд░рдпреЛрдЧреЛрдВ рдХреЛ рдЪрд▓рд╛рдиреЗ рдкрд░ рдореИрдВрдиреЗ рдЕрдзрд┐рдХрддрдо <10% рд░рдирдЯрд╛рдЗрдо рдкреЗрдирд▓реНрдЯреА рдХрд╛ рдЕрд╡рд▓реЛрдХрди рдХрд┐рдпрд╛ рдпрджрд┐ рд╕рд░рдгреА рдмрдбрд╝реА рд╣реИ рдФрд░ рдмрд╣реБрдд рдХрдо NaN рд╣реИрдВ (1 рдорд┐рд▓рд┐рдпрди рдореЗрдВ рд╕реЗ 10 NaN рдХрд╣рддреЗ рд╣реИрдВ), рдФрд░ рдРрд╕реЗ рдмрдбрд╝реЗ рд╕рд░рдгрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рддреЗрдЬреА рд╕реЗ рдЪрд▓рддрд╛ рд╣реИ рдЕрдЧрд░ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╣реИрдВ NaN рдХреЗред

рджреВрд╕рд░реА рдУрд░, рдпрджрд┐ рд╕рд░рдгрд┐рдпрд╛рдБ рдЫреЛрдЯреА рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, 10 рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдБ) рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкреНрд░рджрд░реНрд╢рди рд╣рд┐рдЯ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдлреНрд▓реЛрдЯ рдФрд░ NaN рдХреЗ рд▓рд┐рдП рдЪреЗрдХ рдЕрдкреЗрдХреНрд╖рд╛рдХреГрдд рдорд╣рдВрдЧрд╛ рд╣реИ, рдФрд░ рд░рдирдЯрд╛рдЗрдо рдХрдИ рддрдХ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рддрдм рднреА рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ рдпрджрд┐ рдХреЛрдИ NaN рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЬрд╛рдВрдЪ рд╣реИ рдЬреЛ рдзреАрдореА рд╣реИред

рдпрджрд┐ рд╕рд░рдгреА рдореЗрдВ NaN рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдпрд╣ NaNs рдХреЗ рд╕рдВрдпреЛрдЬрди рд╕реЗ рдПрдХ рдЕрд▓рдЧ рдкрд░рд┐рдгрд╛рдо рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдпрд╣ рд╕рдм рд╣реИред рддреЛ рдЙрд╕ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рд╕рд╡рд╛рд▓ рд╣реИ (рд╕рднреА NaN рдПрдХ рдПрдХрд▓ рдореВрд▓реНрдп рд╕рдореВрд╣ рдореЗрдВ рд╕рдВрдпреБрдХреНрдд) рдереЛрдбрд╝рд╛ рдзреАрдорд╛ рдмрдирд╛рдо рдПрдХ рдЕрд╡рд╛рдВрдЫрд┐рдд рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ (рдкреНрд░рддреНрдпреЗрдХ NaN рдЕрдкрдиреЗ рдореВрд▓реНрдп рд╕рдореВрд╣ рдореЗрдВ) рдереЛрдбрд╝рд╛ рддреЗрдЬред

рдЕрдВрдд рдореЗрдВ, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рдкреИрдЪ NaNs рдпреБрдХреНрдд рдпреМрдЧрд┐рдХ рд╡рд╕реНрддреБрдУрдВ рдЬреИрд╕реЗ рдЕрджреНрд╡рд┐рддреАрдп рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдЦреЛрдЬрдиреЗ рдореЗрдВ рдареАрдХ рдирд╣реАрдВ рд╣реЛрдЧрд╛, рдЬреИрд╕реЗ рдХрд┐ рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ:

a = np.array([[0,1],[np.nan, 1], [np.nan, 1]])
np.unique(a, axis=0)

рдЬреЛ рдЕрднреА рднреА рд▓реМрдЯреЗрдЧрд╛

array([[ 0.,  1.],
       [nan,  1.],
       [nan,  1.]])

"рдЕрдЧрд░ рд╕рд░рдгреА рдореЗрдВ NaN рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдпрд╣ NaNs рдХреЛ рдорд┐рд▓рд╛рдХрд░ рдПрдХ рдЕрд▓рдЧ рдкрд░рд┐рдгрд╛рдо рддреИрдпрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рдпрд╣ рд╕рдм рд╣реИред"

+1

рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЬреЛ рдмрд╛рд░-рдмрд╛рд░ рддрддреНрд╡реЛрдВ рд╕реЗ рдпреБрдХреНрдд рдПрдХ рд╕реВрдЪреА рджреЗрддрд╛ рд╣реИ, _e.g._ 1 NaN рд╕реЗ рдЕрдзрд┐рдХ рдХреЗ рд╕рд╛рде рдПрдХ рд╕реВрдЪреА, рдХреЛ "рдЕрджреНрд╡рд┐рддреАрдп" рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ NaN рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдмрд╛рд░-рдмрд╛рд░ рддрддреНрд╡реЛрдВ рдХреЛ рд╡рд╛рдВрдЫрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓рд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЕрдХреНрд╖рдо рд╣реЛ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП numpy.unique(..., keep_NaN=False) ред

@ufmayer submit a PR!

+1
рдореИрдВ рднреА рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рд╣реА NaN рд╡рд╛рдкрд╕реА рдХрд╛ рд╕рдорд░реНрдерди рдХрд░реВрдВрдЧрд╛

рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕

рд╕рдВрдмрдВрдзрд┐рдд рдореБрджреНрджреЛрдВ

Foadsf picture Foadsf  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

qualiaa picture qualiaa  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

MareinK picture MareinK  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

MorBilly picture MorBilly  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

manuels picture manuels  ┬╖  3рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ