2016-06-17 22 views
16

In Danimarca abbiamo un sistema di classificazione dispari che va come segue. [-3,00,02,4,7,10,12] Il nostro compito è quello di prendere un vettore con numeri decimali diversi e arrotondarlo al voto valido più vicino. Ecco il nostro codice finora.Come arrotondare un numero a un numero intero selezionato

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])) 

La nostra console non sembra come questo e Retuns: TypeError: builtin_function_or_method' oggetto non è subscriptable

Tutto l'aiuto è apprezzato, e se si dispone di un metodo più intelligente siete invitati a metterci al posto nostro.

+3

lì non è assolutamente necessario per Numpy qui. –

+1

@ Ev.Kounis Suppongo che Numpy sia usato per una buona ragione e che questo sia solo un esempio di giocattolo, altrimenti suggerirei semplicemente di usare una lista con la funzione 'map' incorporata. –

risposta

18

Si potrebbe semplicemente prendere la distanza minima da ciascun grado a ciascun gruppo di gradi, in questo modo. Questo presuppone che tu voglia effettivamente arrotondare al grado più vicino dal tuo gruppo di livello, che il tuo codice attuale non fa esattamente.

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) 

Uscite:

[-3, 7, 10, 10] 

notare che, anche dopo aver fissato il vostro errore il tuo approccio non è ancora funziona perché roundGrade aspetta un singolo numero come parametro. As shown by juanapa puoi vettorializzare la tua funzione.

1

Bene, anche senza testare il codice, posso vedere alcuni problemi qui.

La tua funzione, roundGrade, prende un numero e restituisce un numero, ma quando lo chiami, fornisci un array. Assumendo che il rientro è ok e la chiamata non è all'interno della funzione, vorrei fare qualcosa di simile:

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) 

chiamata al metodo e fornendo una matrice non è ok, durante la chiamata che il metodo con ciascuno degli elementi è ok , perché il metodo dovrebbe ricevere un numero e non un array.

0

Per quanto riguarda l'eccezione, l'array NumPy è una funzione, e aveva bisogno di essere chiamato con() Così la vostra chiamata al metodo dovrebbe essere come:

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

e non:

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

Come per la funzione stessa, utilizzare grades.any() o grades.all() per verificare gli elementi interi, altrimenti il ​​confronto non è definito.

1

Ecco come lo farei:

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'] 

prende una lista e restituisce uno. Gestisce l'input fuori campo e gli elementi di elenco restituiti sono stringhe anziché numeri interi per aggiungere quel carattere "00" e non "0".

25

Hai trovato questo errore, perché quando si stampa, si sta utilizzando la sintassi corretta:

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

deve essere

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

Notare le parentesi aggiuntive: np.array(<whatever>)

Tuttavia, questo non funzionerà, dal momento che la tua funzione si aspetta un singolo numero.Fortunatamente, NumPy fornisce una funzione che può risolvere per voi:

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

3

avrei rotonda calcolando quale grado valida è più vicina alla e il ritorno che uno:

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

Questo ovviamente consente solo di passare un singolo voto alla volta, ma puoi semplicemente ripetere il ciclo sulla tua matrice di decimali, sia al di fuori della funzione che al suo interno per renderla compatibile con gli array.

2
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])) 

è meno efficiente (credo), ma è il codice molto più piccolo
Esso crea un dizionario in cui la chiave è un grado rotondo e il valore è la differenza tra il grado rotonda e il dato grado
Poi trova il valore minimo (più piccola differenza) e restituisce la chiave (il valore arrotondato
Poi si utilizza solo map di applicare questa funzione su ogni elemento dell'elenco

2

penso che si potrebbe essere in grado di farlo in uno rivestimento utilizzando solo elenchi:

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] 

si può rompere questo in giù come:

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 
1

Hai trovato questo errore a causa della parentesi in più nella linea

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

si dovrebbe essere

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