Как округлить число до выбранного целого числа

В Дании мы имеем нечетную систему оценок, которая выглядит следующим образом. [-3,00,02,4,7,10,12] Наше задание - взять вектор с разными десятичными числами и округлить его до ближайшего действительного класса. Вот наш код.

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

Наша консоль, похоже, не нравится и перенастраивает: Объект TypeError: builtin_function_or_method не подлежит расшифровке

Вся помощь приветствуется, и если у вас есть более умный метод, вы можете поставить нас на место.

Ответы

Ответ 1

Вы можете просто взять минимальное расстояние от каждого класса до каждой группы классов, например. Это предполагает, что вы действительно хотите округлить до ближайшего класса от вашей группы классов, что ваш текущий код не делает точно.

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)

Результаты

[-3, 7, 10, 10]

Обратите внимание, что даже после исправления ошибки ваш подход еще не будет работать, потому что roundGrade ожидает, что в качестве параметра будет указано одно число. Как показано juanapa, вы можете оцифровать свою функцию.

Ответ 2

Вы получаете эту ошибку, потому что когда вы печатаете, вы используете неправильный синтаксис:

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

должно быть

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

Обратите внимание на дополнительные круглые скобки: np.array(<whatever>)

Однако это не сработает, так как ваша функция ожидает единственное число. К счастью, numpy предоставляет функцию, которая может исправить это для вас:

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

Я бы округлял, вычисляя, какой действительный класс он ближе всего и возвращает тот:

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

Это, конечно, позволяет вам одновременно передавать только один класс, но вы можете просто перебирать массив десятичных знаков либо вне функции, либо внутри нее, чтобы сделать ее совместимой с массивом.

Ответ 4

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

Он менее эффективен (я думаю), но намного меньше кода
Он создает словарь, где ключ представляет собой круглый класс, а значение - это разница между круглой степенью и данным классом Затем он находит минимальное значение (наименьшая разница) и возвращает ключ (округленное значение
Затем он просто использует map для применения этой функции к каждому элементу в списке

Ответ 5

Я думаю, что вы можете сделать это в одном лайнере, используя только списки:

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]

Вы можете разбить это как:

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

Ответ 6

Ну, даже без тестирования кода я вижу здесь некоторые проблемы.

Ваша функция roundGrade принимает номер и возвращает число, но когда вы его вызываете, вы предоставляете ему массив. Предполагая, что ваш отступ в порядке, а вызов не находится внутри функции, я бы сделал что-то вроде этого:

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)

Вызов метода и предоставление массива не в порядке, при вызове этого метода с каждым из элементов в порядке, потому что метод должен получать число, а не массив.

Ответ 7

Вот как я это сделаю:

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

Получает список и возвращает его. Обрабатывает вывод вне диапазона и возвращаемые элементы списка - это строки вместо целых чисел, чтобы добавить это фантастическое "00", а не "0".

Ответ 8

Вы получаете эту ошибку из-за дополнительной скобки в строке

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

должен быть

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

Ответ 9

Что касается исключения, массив numpy является функцией и должен быть вызван с() Поэтому ваш вызов метода должен выглядеть следующим образом:

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

и не:

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

Что касается самой функции, либо используйте grades.any() или grades.all(), чтобы проверить все элементы, иначе сравнение не определено.