Tengo el siguiente código

import numpy
s = numpy.array([['210123278414410005', '101232784144610006']], dtype='object')
print(s, type(s), s.shape)
s[0][0] = s[0][0][13:]
s[0][1] = s[0][1][13:]    
print(s, type(s), s.shape)

Esto me da el resultado deseado:

[['210123278414410005' '101232784144610006']] 
[['10005' '10006']]

Como puede ver, 13 caracteres a la izquierda se han ido. ¿Es posible transmitir esta operación?

Lo intenté

s[0][:] = [[s[0][0]]][0][0][13:]

Pero esto no da la salida correcta como antes.

[['10005' '10005']] 
0
prosti 10 may. 2019 a las 01:47

4 respuestas

La mejor respuesta
In [22]: s = np.array([['210123278414410005', '101232784144610006']], dtype='object')                                                                  
In [23]: s                                                                      
Out[23]: array([['210123278414410005', '101232784144610006']], dtype=object)
In [24]: s.shape                                                                
Out[24]: (1, 2)

Como se trata de una matriz dtype de objetos, un buen punto de partida es frompyfunc que también devuelve una matriz dtype de objetos:

In [25]: np.frompyfunc(lambda s: s[13:],1,1)(s)                                 
Out[25]: array([['10005', '10006']], dtype=object)

s[0,0] es una cadena de Python. s[0,0][13:] es una operación de cadena.

En general, las operaciones en matrices dtype de objeto requieren una iteración de nivel cercano a Python, incluso matemáticas. No hay ninguna operación integrada numpy para tomar subcadenas. np.char tiene un montón de funciones que aplican métodos de cadena a elementos de una matriz dtype de cadena. Pero no son particularmente rápidos, y no incluyen esta tarea de subcadena.

O para los últimos 5:

In [33]: np.frompyfunc(lambda s: s[-5:],1,1)(s)                                 
Out[33]: array([['10005', '10006']], dtype=object)

Comparando esto con la respuesta de Colin:

In [37]: sbig = np.resize(s, (1000,1000))                                       
In [38]: timeit np.mod(sbig.astype('uint64'),100000).astype('U')                
754 ms ± 9.33 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [39]: timeit np.frompyfunc(lambda s: s[-5:],1,1)(sbig)                       
245 ms ± 428 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)

Mirando más lejos, parece que el paso astype('U') es el gran consumidor, convirtiendo números en cadenas.

2
hpaulj 11 may. 2019 a las 05:48

Puede convertir sus elementos de matriz en números, recortarlos y luego volver a convertirlos en cadenas:

WIDTH = 5
MOD = 10 ** WIDTH
numpy.char.zfill((s.astype(numpy.int64) % MOD).astype('str'), WIDTH)
#array([['10005', '10006']], dtype='<U5')
1
DYZ 9 may. 2019 a las 23:16

Usa la comprensión

import numpy
s = numpy.array([['210123278414410005', '101232784144610006']], dtype='object')
s = np.asarray([[i[13:] for e in s for i in e]])
print(s, type(s), s.shape)

Resultado:

[['10005' '10006']] <class 'numpy.ndarray'> (1, 2)
1
âńōŋŷXmoůŜ 9 may. 2019 a las 22:58

Un enfoque torpe sería convertir su 'cadena de números' en un número entero, realizar un módulo a la longitud deseada y luego volver a convertirlo en una cadena:

s = numpy.mod(s[0,].astype(numpy.uint64),100000).astype('U')

Lo que da el resultado deseado.

1
Colin Dickie 9 may. 2019 a las 23:42