【问题标题】:Use a dictionary to key a range of values [duplicate]使用字典来键入一系列值[重复]
【发布时间】:2020-06-16 00:53:40
【问题描述】:

我有一个 pandas 数据框,我想根据另一列的值在新列中创建类别。我可以通过这样做来解决我的基本问题:

range = {
    range(0, 5) : 'Below 5',
    range(6,10): 'between',
    range(11, 1000) : 'above'
}

df['range'] = df['value'].map(range)

在最终的字典键中,我为范围选择了一个较大的上限值,以确保它捕获我尝试映射的所有值。然而,这似乎是一个丑陋的黑客,我想知道如何在不指定上限的情况下概括这一点。 IE。 if > 10 : '高于'。

谢谢

【问题讨论】:

标签: python python-3.x pandas


【解决方案1】:

您可以先将所有值设置为“以上”,然后将map() 用于其余选项(因此您的range dict 只有两个项目):

range = {
    range(0, 5) : 'Below 5',
    range(6,10): 'between',

}
df['range'] = 'above'
df['range'] = df['value'].map(range)

【讨论】:

    【解决方案2】:
     df['range'] = pd.cut(df['value'], bins = [0, 5, 10, 1000], labels = ["below 5", "between", "above"])
    

    【讨论】:

    • 这仍然会受到设置相当任意的上限的影响(当然可以使用max(df['value'])
    【解决方案3】:

    感谢您的提示。我知道我可以通过以下方式实现相同的目标:

    df['range'] = df['value'].map(range).fillna('above')
    

    【讨论】:

      【解决方案4】:

      这是使用numpy.select 的另一种方法,您可以在其中指定一个布尔条件列表和一个选项列表:

      import numpy as np 
      
      # Setup
      df = pd.DataFrame({'value': [1, 3, 6, 8, 20, 10000000]})
      
      condlist = [
          df['value'].lt(5),
          df['value'].between(5, 10),
          df['value'].gt(10)]
      
      choicelist = ['Below 5', 'between', 'above']
      
      df['out'] = np.select(condlist, choicelist)
      print(df)
      

      [出]

            value      out
      0         1  Below 5
      1         3  Below 5
      2         6  between
      3         8  between
      4        20    above
      5  10000000    above
      

      另一个想法是使用 pandas.cut 并指定 binslabels 参数:

      df['out'] = pd.cut(df['value'], bins=[-np.inf, 5, 10, np.inf],
                         labels=['below', 'between', 'above'])
      
            value      out
      0         1    below
      1         3    below
      2         6  between
      3         8  between
      4        20    above
      5  10000000    above
      

      【讨论】:

        【解决方案5】:

        假设你有一个这样的数据框:

          range value
        0   0     0
        1   1     1
        2   2     2
        3   3     3
        4   4     4
        5   5     5
        6   6     6
        7   7     7
        8   8     8
        9   9     9
        

        然后您可以将以下函数应用到“值”列:

        def get_value(range):
            if range < 5:
                return 'Below 5'
            elif range < 10:
                return 'Between 5 and 10'
            else:
                return 'Above 10'
        
        df['value'] = df.apply(lambda col: get_value(col['range']), axis=1)
        

        为了得到你想要的结果。

        【讨论】:

          【解决方案6】:

          pandas.Series.map 也接受 function 作为第一个参数,所以你可以这样做:

          def fun(x):
              if x in range(0, 5):
                  return 'Below 5'
              elif x in range(6, 10):
                  return 'between'
              elif x >= 11:
                  return 'above'
          

          然后:

          df['range'] = df['value'].map(fun)
          

          【讨论】:

          • 哦,很好。现在用带有嵌套三元比较的 lambda 函数替换 run,将所有内容都变成一行。我猜df['range'] = df['value'].map(lambda x: 'Below 5' if in x range(0, 5) else ('between' if x in (range(6, 10) else 'above')) 可以做到。
          • @0 0:对我来说,单行嵌套ifs 的可读性不是很好。如果在这种情况下我能以任何价格放入 1 行,那么我宁愿这样做:f = lambda x:('Below 5','between','above')[(x&gt;=5)+(x&gt;=11)]
          • 也不错。我肯定会选择混淆的 Python 单行代码。幸运的是,在 Python 中,True + True == 2.
          猜你喜欢
          • 1970-01-01
          • 2019-11-13
          • 2016-09-29
          • 2021-01-01
          • 2013-05-22
          • 2013-09-21
          • 2021-09-16
          • 2014-04-05
          • 2020-11-08
          相关资源
          最近更新 更多