如何将范围的映射转换为字典

时间:2018-12-13 15:46:07

标签: python dictionary categorical-data

如何将其转换为字典?

if grade>=96.5:return 5.83
elif grade>=92.5:return 5.5
elif grade>=89.5:return 5.16
elif grade>=86.5:return 4.83
elif grade>=82.5:return 4.5
elif grade>=79.5:return 4.16
elif grade>=76.5:return 3.83
elif grade>=72.5:return 3.5
elif grade>=69.5:return 3.16
elif grade>=68.5:return 2.83
elif grade>=64.5:return 2.5
else:return 0

我知道如何制作基本词典,但是,我不确定它是否看起来像这样:

grade_checker = {
    grade>96.5:5.83
}

谢谢!

10 个答案:

答案 0 :(得分:5)

简短的答案是您不应该将其转换为字典。这最适合作为函数使用,似乎您只是缺少函数定义,因为我看到您在代码中使用了return。字典是由键值对构成的,并且由于您的条件涉及>=个评估,因此不适合使用字典。请参见下面的函数实现:

def grade_checker(grade):

    if grade>=96.5: return 5.83
    elif grade>=92.5: return 5.5
    elif grade>=89.5: return 5.16
    elif grade>=86.5: return 4.83
    elif grade>=82.5: return 4.5
    elif grade>=79.5: return 4.16
    elif grade>=76.5: return 3.83
    elif grade>=72.5: return 3.5
    elif grade>=69.5: return 3.16
    elif grade>=68.5: return 2.83
    elif grade>=64.5: return 2.5
    else: return 0

grade_checker(75)
grade_checker(62)
grade_checker(94)

返回:

3.5
0
5.5

答案 1 :(得分:3)

没有字典,您可以解决以下问题:

<img src={process.env.PUBLIC_URL + "/photo/IMG_0509.jpg"} />

这比字典更可取,因为仅对于> = Python 3.6,内置字典可保证有序性(即,它们将以插入键/值的顺序进行迭代)。能够在更多Python版本上运行代码胜于依赖于特定的版本细节。

答案 2 :(得分:3)

可以使用词典来保存评分信息,但是它不能真正提供任何好处,因为您无法对这些范围使用快速词典查找。相反,我建议使用(points, grade)对的排序列表,然后使用bisect对O(logn)中的匹配分数进行二进制搜索。

>>> import bisect
>>> grade_ranges = [(0, 0), (64.5, 2.5), (68.5, 2.83), (69.5, 3.16), 
...                 (72.5, 3.5), (76.5, 3.83), (79.5, 4.16), (82.5, 4.5), 
...                 (86.5, 4.83), (89.5, 5.16), (92.5, 5.5), (96.5, 5.83)]
...
>>> points, grade = zip(*grade_ranges)
>>> grade[bisect.bisect(points, 96.5)-1]
5.83
>>> grade[bisect.bisect(points, 73)-1]
3.5
>>> grade[bisect.bisect(points, 30)-1]
0

grade_ranges分别解压缩到pointsscores是可选的,但是恕我直言,这样比较干净。如果您不解压缩,则必须将一个元组传递给bisect,例如bisect(grade_ranges, (55,))

答案 3 :(得分:2)

如果您确实需要使用字典,这将是一种方法;将字典键作为条件检查值,并将字典值作为要返回的值。

grade_checker = {
    96.5: 5.83,
    92.5: 5.5,
    89.5: 5.16,
    86.5: 4.83,
    82.5: 4.5,
    79.5: 4.16,
    76.5: 3.83,
    72.5: 3.5,
    69.5: 3.16,
    68.5: 2.83,
    64.5: 2.5
}

def check_grade(grade):
    for k in grade_checker:
        if grade >= k:
            return grade_checker[k]
    return 0

检查

>>> check_grade(45.5)
0
>>> check_grade(65.5)
2.5
>>> check_grade(95)
5.5

答案 4 :(得分:2)

另一种选择是使用range-key-dict

from range_key_dict import RangeKeyDict

range_key_dict = RangeKeyDict({
    (96.5, 100): 5.83,
    (92.5, 96.5): 5.5,
    (89.5, 92.5): 5.16,
    (86.5, 89.5): 4.83,
    (82.5, 86.5): 4.5,
    (79.5, 82.5): 4.16,
    (76.5, 79.5): 3.83,
    (72.5, 76.5): 3.5,
    (69.5, 72.5): 3.16,
    (68.5, 69.5): 2.83,
    (64.5, 68.5): 2.5,
    (0, 64.5): 0
})

assert range_key_dict[96.5] == 5.83
assert range_key_dict[96.4] == 5.5
assert range_key_dict[96.49] == 5.5

您可以使用pip install range-key-dict安装此Python软件包。

您还需要检查源代码的复杂性,因为它不会像常规字典那样维护O(1)哈希。

仅使用常规的if语句可能更容易,更有效。

答案 5 :(得分:2)

如果您要存储键值对并希望能够真正快速地检索任意条目,则标记特别有用。如其他答案所示,您只需要遍历元素序列并使用第一个匹配的元素的值即可。因此,最直接(也是最有效)的策略是使用序列数据类型。这是代码中的样子:

export default withAuthenticator(App);

技巧很棒,但是如果您不需要它们的功能,请使用更简单的方法。

答案 6 :(得分:2)

如果您可以使用第三方库,则可以通过pd.cut使用熊猫。如果您要分类的输入等级很多,这将特别有效。

import pandas as pd

grade_checker = {96.5: 5.83,
                 ...,
                 64.5: 2.5}

keys, values = zip(*sorted(grade_checker.items()))
keys += (float('inf'),)  # need to add upper boundary for pd.cut input

grade = 65.5
res = pd.cut([grade], keys, labels=values).astype(float)[0]  # 2.5

查看相关内容:How to map numeric data into categories / bins in Pandas dataframe

答案 7 :(得分:1)

如果在3.6之前的版本中使用Python,则可以使用collections.OrderedDict(包括Python 2.7),否则dict对象是按插入顺序排序的(see here for more)对象!

这样,您可以简单地遍历dict并返回第一个范围匹配项。

# python 3.6+
grade_table = {
    96.5: 5.83,
    ...
    64.5: 2.5,
}

# pre-3.6
from collections import OrderedDict
grade_table = OrderedDict((  # this is a tuple of tuples
    (96.5, 5.83),
    ...
    (64.5, 2.5),
))

def fn(student_grade):
    for grade, value in grade_table.iteritems():
        if student_grade >= grade:
            return value

    return 0  # default

请注意,如果您希望表发生变化,则可能有必要测试dict是降序还是始终接受可迭代的可迭代对象,然后对它们进行排序(我在上面使用了一个元组,但是相同的表格应该可以工作,并且易于排序),否则会返回错误的结果。

答案 8 :(得分:0)

不可能将此逻辑转换为字典。字典是键值对,因此无法仅通过查找就可以进行“大于”检查。

答案 9 :(得分:0)

我不是数学家,但认为插值可能对此有用吗?

    from numpy import interp

    ak = [k for k in gc.keys()]
    av = [v for v in gc.values()]

    # np.interp needs values from lowest to highest
    ak.reverse()
    av.reverse()

    interp(79, ak, av)
    >>> 4.105

    interp(96, ak, av)
    >>> 5.78875

    interp(64, ak, av)
    >>> 2.5

您需要向上和向下填充100个,因为它是插值,因此您需要关注的数据点必须在 个样本范围内。