Pregunta

Esto debería ser fácil.

Aquí está mi matriz (más bien, un método para generar matrices de prueba representativas):

>>> ri = numpy.random.randint
>>> ri2 = lambda x: ''.join(ri(0,9,x).astype('S'))
>>> a = array([float(ri2(x)+ '.' + ri2(y)) for x,y in ri(1,10,(10,2))])
>>> a
array([  7.99914000e+01,   2.08000000e+01,   3.94000000e+02,
         4.66100000e+03,   5.00000000e+00,   1.72575100e+03,
         3.91500000e+02,   1.90610000e+04,   1.16247000e+04,
         3.53920000e+02])

Quiero una lista de cadenas donde '\ n'.join (list_o_strings) se imprimiría:

   79.9914
   20.8
  394.0
 4661.0
    5.0
 1725.751
  391.5
19061.0
11624.7
  353.92

Quiero espaciar la almohadilla a la izquierda y a la derecha (pero no más de lo necesario).

Quiero un cero después del decimal si eso es todo lo que está después del decimal.

No quiero notación científica.

... y no quiero perder ningún dígito significativo. (en 353.98000000000002 el 2 no es significativo)

Sí, es bueno querer ...

Python 2.5's % g,% fx.x , etc. me están confundiendo o no pueden hacerlo. Todavía no he probado import decimal . No puedo ver que NumPy lo haga (aunque, la matriz .__ str __ y array .__ repr__ están alineados con decimales (pero a veces son científicos).

Ah, y la velocidad cuenta. Estoy tratando con grandes matrices aquí.

Mis enfoques de solución actuales son:

  1. para str (a) y analizar los corchetes de NumPy
  2. a str (e) cada elemento en la matriz y dividir ('.') luego rellenar y reconstruir
  3. a a.astype ('S' + str (i)) donde i es el máximo (len (str (a))), luego pad

Parece que debería haber alguna solución lista para usar ... (pero no es obligatorio)

La sugerencia principal falla cuando dtype es float64:

>>> a
array([  5.50056103e+02,   6.77383566e+03,   6.01001513e+05,
         3.55425142e+08,   7.07254875e+05,   8.83174744e+02,
         8.22320510e+01,   4.25076609e+08,   6.28662635e+07,
         1.56503068e+02])
>>> ut0 = re.compile(r'(\d)0+)
>>> thelist = [ut0.sub(r'\1', "%12f" % x) for x in a]
>>> print '\n'.join(thelist)
  550.056103
 6773.835663
601001.513
355425141.8471
707254.875038
  883.174744
   82.232051
425076608.7676
62866263.55
  156.503068
¿Fue útil?

Solución

Lo siento, pero después de una investigación exhaustiva, no puedo encontrar ninguna manera de realizar la tarea que necesita sin un mínimo de procesamiento posterior (para quitar los ceros finales que no desea ver); algo como:

import re
ut0 = re.compile(r'(\d)0+

es rápido y conciso, pero rompe su restricción de estar "listo para usar" - es, en cambio, una combinación modular de formato general (que casi hace lo que quiere pero deja el cero final que desea ocultar) y un RE para eliminar los ceros finales no deseados. Prácticamente, creo que hace exactamente lo que usted requiere, pero creo que sus condiciones, según lo establecido, son demasiado limitadas.

Editar : la pregunta original se editó para especificar dígitos más significativos, no requiere espacio inicial adicional más allá de lo que se requiere para el número más grande y proporciona un nuevo ejemplo (donde mi sugerencia anterior, arriba, no t coincida con la salida deseada). El trabajo de eliminar espacios en blanco iniciales que es común a un grupo de cadenas se realiza mejor con textwrap.dedent - pero eso funciona en una sola cadena (con nuevas líneas) mientras que la salida requerida es una lista de cadenas. No hay problema, solo juntaremos las líneas, las abollaremos y las dividiremos nuevamente:

import re
import textwrap

a = [  5.50056103e+02,   6.77383566e+03,   6.01001513e+05,
         3.55425142e+08,   7.07254875e+05,   8.83174744e+02,
         8.22320510e+01,   4.25076609e+08,   6.28662635e+07,
         1.56503068e+02]

thelist = textwrap.dedent(
        '\n'.join(ut0.sub(r'\1', "%20f" % x) for x in a)).splitlines()

print '\n'.join(thelist)

emite:

      550.056103
     6773.83566
   601001.513
355425142.0
   707254.875
      883.174744
       82.232051
425076609.0
 62866263.5
      156.503068
) thelist = [ut0.sub(r'\1', "%12f" % x) for x in a] print '\n'.join(thelist)

es rápido y conciso, pero rompe su restricción de estar "listo para usar" - es, en cambio, una combinación modular de formato general (que casi hace lo que quiere pero deja el cero final que desea ocultar) y un RE para eliminar los ceros finales no deseados. Prácticamente, creo que hace exactamente lo que usted requiere, pero creo que sus condiciones, según lo establecido, son demasiado limitadas.

Editar : la pregunta original se editó para especificar dígitos más significativos, no requiere espacio inicial adicional más allá de lo que se requiere para el número más grande y proporciona un nuevo ejemplo (donde mi sugerencia anterior, arriba, no t coincida con la salida deseada). El trabajo de eliminar espacios en blanco iniciales que es común a un grupo de cadenas se realiza mejor con textwrap.dedent - pero eso funciona en una sola cadena (con nuevas líneas) mientras que la salida requerida es una lista de cadenas. No hay problema, solo juntaremos las líneas, las abollaremos y las dividiremos nuevamente:

<*>

emite:

<*>

Otros consejos

El formato de cadena de Pythons puede imprimir solo los decimales necesarios (con% g) o utilizar un conjunto fijo de decimales (con% f). Sin embargo, desea imprimir solo los decimales necesarios, excepto si el número es un número entero, entonces quiere un decimal, y eso lo hace complejo.

Esto significa que terminarías con algo como:

def printarr(arr):
    for x in array:
        if math.floor(x) == x:
            res = '%.1f' % x
        else:
            res = '%.10g' % x
        print "%*s" % (15-res.find('.')+len(res), res)

Esto creará primero una cadena con 1 decimal, si el valor es un número entero, o se imprimirá con decimales automáticos (pero solo hasta 10 números) si no es un número fraccionario. Por último, lo imprimirá, ajustado para que el punto decimal esté alineado.

Probablemente, sin embargo, numpy realmente hace lo que quieres, porque normalmente quieres que esté en modo exponencial si es demasiado largo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top