round array python numpy rounding

python - array - Cómo redondear un número a un entero elegido



round np array python (10)

En Dinamarca tenemos un sistema de calificación impar que va de la siguiente manera. [-3,00,02,4,7,10,12] Nuestra tarea es tomar un vector con diferentes números decimales y redondearlo a la calificación válida más cercana. Aquí está nuestro código hasta ahora.

import numpy as np def roundGrade(grades): if (-5<grades<-1.5): gradesRounded = -3 elif (-1.5<=grades<1.5): gradesRounded = 00 elif (1.5<=grades<3): gradesRounded = 2 elif (3<=grades<5.5): gradesRounded = 4 elif (5.5<=grades<8.5): gradesRounded = 7 elif (8.5<=grades<11): gradesRounded = 10 elif (11<=grades<15): gradesRounded = 12 return gradesRounded print(roundGrade(np.array[-2.1,6.3,8.9,9]))

Parece que a nuestra consola no le gusta esto y vuelve a funcionar: TypeError: builtin_function_or_method ''object no es suscriptible

Se agradece toda la ayuda y, si tiene un método más inteligente, puede ponerse en nuestro lugar.


Así es como lo haría:

def roundGrade(grades_in): grades_out = [] for grades in grades_in: if grades < -5 or grades > 15: gradesRounded = ''??'' print(''Grade input out of range ({:})!''.format(grades)) if (-5<grades<-1.5): gradesRounded = ''-3'' elif (-1.5<=grades<1.5): gradesRounded = ''00'' elif (1.5<=grades<3): gradesRounded = ''2'' elif (3<=grades<5.5): gradesRounded = ''4'' elif (5.5<=grades<8.5): gradesRounded = ''7'' elif (8.5<=grades<11): gradesRounded = ''10'' elif (11<=grades<15): gradesRounded = ''12'' grades_out.append(gradesRounded) return grades_out grades_in = [-7, -2.1, 0.1, 6.3, 8.9, 9] print(roundGrade(grades_in)) #prints: [''??'', ''-3'', ''00'', ''7'', ''10'', ''10'']

Toma una lista y devuelve una. Los controles de entrada fuera de rango y los elementos de lista devueltos son cadenas en lugar de números enteros para agregar ese "00" de lujo y no "0".


Bueno, incluso sin probar su código, puedo ver algunos problemas aquí.

Su función, roundGrade , toma un número y devuelve un número, pero cuando lo llama, le proporciona una matriz. Suponiendo que su sangría esté bien y que la llamada no esté dentro de la función, haría algo como eso:

def roundGrade(grades): if (-5<grades<-1.5): gradesRounded = -3 elif (-1.5<=grades<1.5): gradesRounded = 00 elif (1.5<=grades<3): gradesRounded = 2 elif (3<=grades<5.5): gradesRounded = 4 elif (5.5<=grades<8.5): gradesRounded = 7 elif (8.5<=grades<11): gradesRounded = 10 elif (11<=grades<15): gradesRounded = 12 return gradesRounded #print(roundGrade(np.array[-2.1,6.3,8.9,9])) # Here, I assume you want to round each of the grades in the array. If I''m wrong, comment, please! for i in [-2.1, 6.3, 8.9, 9]: print roundGrade(i)

No es correcto llamar al método y proporcionar una matriz, mientras que llamar a ese método con cada uno de los elementos es correcto, ya que se supone que el método recibe un número y no una matriz.


Creo que podrías hacerlo en una sola línea usando solo listas:

l = [-2.1,6.3,8.9,9] b = [-3,0,02,4,7,10,12] a = [b[min(enumerate([abs(j - item) for j in b]), key=lambda p:p[1])[0]] for item in l] >>> [-3, 7, 10, 10]

Puedes descomponerlo como:

min(enumerate([abs(j - item) for j in b]), key=lambda p:p[1])[0] # Find the index of the nearest grade boundary [b[...] for item in l] # Get the associated grade boundary for all the items in the original list


En cuanto a la excepción, la matriz numpy es una función, y debe llamarse con () Por lo tanto, su llamada al método debería ser como:

print(roundGrade(np.array([-2.1,6.3,8.9,9])))

y no:

print(roundGrade(np.array[-2.1,6.3,8.9,9]))

En cuanto a la función en sí misma, utilice calificaciones.cualquier () o calidades.todos () para probar los elementos completos, de lo contrario, la comparación no está definida.


Recibes ese error porque cuando imprimes, estás usando una sintaxis incorrecta:

print(roundGrade(np.array[-2.1,6.3,8.9,9]))

necesita ser

print(roundGrade(np.array([-2.1,6.3,8.9,9])))

Observe los paréntesis adicionales: np.array(<whatever>)

Sin embargo, esto no funcionará, ya que su función espera un solo número. Afortunadamente, numpy proporciona una función que puede solucionarlo:

In [15]: roundGrade = np.vectorize(roundGrade) In [16]: roundGrade(np.array([-2.1,6.3,8.9,9])) Out[16]: array([-3, 7, 10, 10])

http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.vectorize.html


Recomendaría usar numpy.digitize aquí, ya que le permite vectorizar fácilmente esta operación.

Preparar

bins = np.array([-5, -1.5, 1.5, 3, 5.5, 8.5, 11, 15]) outputs = np.array([-3, 0, 2, 4, 7, 10, 12]) grades = np.array([-2.1, 6.3, 8.9, 9. ])

Utilizando numpy.digitize :

outputs[np.digitize(grades, bins)-1]

array([-3, 7, 10, 10])

A pesar de que otras respuestas han mostrado cómo usar np.vectorize , la digitize seguirá np.vectorize un gran aumento de rendimiento cuando se agrupan los valores:

_v_round_grade = np.vectorize(roundGrade) grades = np.random.randint(-4, 14, 10000)

In [496]: %timeit _v_round_grade(grades) 5.64 ms ± 24.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) In [497]: %timeit outputs[np.digitize(grades, bins)-1] 210 µs ± 567 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Validación

>>> np.array_equal(_v_round_grade(grades), outputs[np.digitize(grades, bins)-1]) True

El uso de esta función de digitize integrada es 25 veces más rápido que simplemente vectorizar su propia función.


Redondearía calculando qué grado válido es el más cercano y devolviéndolo:

import numpy as np def roundGrade(grade): validGrades = np.array([-3,0,2,4,7,10,12]) return validGrades[np.argmin((grade-validGrades)**2)]

Por supuesto, esto solo le permite aprobar un solo grado a la vez, pero solo puede pasar sobre su matriz de decimales, ya sea fuera de la función o dentro de ella para hacerla compatible con la matriz.


Simplemente puede tomar la distancia mínima de cada grado a cada grupo de grado, así. Esto supone que realmente desea redondear a la calificación más cercana de su grupo de calificaciones, lo que su código actual no hace exactamente.

grade_groups = [-3,0,2,4,7,10,12] sample_grades = [-2.1,6.3,8.9,9] grouped = [min(grade_groups,key=lambda x:abs(grade-x)) for grade in sample_grades] print(grouped)

Salidas :

[-3, 7, 10, 10]

Tenga en cuenta que incluso después de corregir su error, su enfoque aún no funcionará porque roundGrade espera un solo número como parámetro. Como lo muestra juanapa usted podría vectorizar su función.


Usted está recibiendo ese error debido al paréntesis adicional en la línea

print(roundGrade(np.array([-2.1,6.3,8.9,9])))

debe ser

print(roundGrade(np.array[-2.1,6.3,8.9,9]))


def roundGrade(grade): d = {x:abs(x - grade) for x in [-3,00,02,4,7,10,12]} return min(d, key=d.get) print list(map(roundGrade, [-2.1, 6.3, 8.9, 9]))

Es menos eficiente (creo) pero es un código mucho más pequeño
Crea un diccionario en el que la clave es una calificación redonda y el valor es la diferencia entre la calificación redonda y la calificación dada
Luego encuentra el valor mínimo (la diferencia más pequeña) y devuelve la clave (el valor redondeado
Luego solo usa el map para aplicar esta función sobre cada elemento de la lista