【问题标题】:Pandas : How to replace values in a range with a string?Pandas:如何用字符串替换范围内的值?
【发布时间】:2018-05-26 22:50:47
【问题描述】:

我正在尝试将某个范围内的值替换为其他值。

我有一个字典,其中包含作为键的字符和作为值的上限,如下所示 -

replace_dict = {
        'A': 10, 
        'B': 21, 
        'C': 34, 
        'D': 49, 
        'E': 66, 
        'F': 85, 
        'G': 107, 
        'H': 132, 
        'I': 160, 
        'J': 192, 
        'K': 229, 
        'L': 271, 
        'M': 319, 
        'N': 395, 
        'O': 495, 
        'P': 595, 
        'Q': 795, 
        'R': 1100
}

我需要将值替换为某个范围内的相应键。

例如:

Values in the range of 1-10 will be replaced by 'A',
Values in the range of 11-21 will be replaced by 'B'
Values in the range of 22-34 will be replaced by 'C'
Values in the range of 35-50 will be replaced by 'D'
Values in the range of 51-66 will be replaced by 'E'

我写了以下代码:

k=1
for i, j in replace_dict.items():
    data.loc[data['my_col'].between(k,j)] = i
    k=j+1

此代码显示TypeError: '>=' not supported between instances of 'str' and 'int'

但是,data.loc[data['my_col'].between(1,10)] = 'A' 行工作正常。

这个问题有什么好的解决方案?

【问题讨论】:

  • 只是反转 i 和 j
  • data['my_col'] 的数据类型是str?试试data['my_col'],astype('int32').between(k,j)

标签: python python-3.x pandas dataframe


【解决方案1】:

您可以使用pandas.cut。需要注意的几点:

  1. 我们使用dict.keysdict.values 的事实排序是一致的。
  2. 我们明确提供binslabels;请注意,labels 必须比 bins 少一项。
  3. 您可能希望为高于 1100 的值添加一个额外的 bin。

这是一个最小的例子。

df = pd.DataFrame({'col': [500, 123, 56, 12, 1000, 2, 456]})

df['mapped'] = pd.cut(df['col'],
                      bins=[1]+list(replace_dict.values()),
                      labels=list(replace_dict.keys()))

print(df)

    col mapped
0   500      P
1   123      H
2    56      E
3    12      B
4  1000      R
5     2      A
6   456      O

【讨论】:

    【解决方案2】:

    您可以使用所需的范围创建单独的 DataFrame,并使用 intervalIndex 创建 map

    设置

    ranges = pd.DataFrame(replace_dict, index=['STOP']).T.reset_index()
    ranges['START'] = (ranges.STOP.shift(1)+1).fillna(1)
    ranges.index = pd.IntervalIndex.from_arrays(ranges.START, ranges.STOP, closed='both')
    
                    index  STOP  START
    [1.0, 10.0]         A    10    1.0
    [11.0, 21.0]        B    21   11.0
    [22.0, 34.0]        C    34   22.0
    [35.0, 49.0]        D    49   35.0
    [50.0, 66.0]        E    66   50.0
    etc...
    

    map 使用您的 intervalIndex

    df = pd.DataFrame({'nums': np.random.randint(1, 1000, 10)})
       nums
    0   699
    1   133
    2   829
    3   299
    4   306
    5   691
    6   172
    7   225
    8   522
    9   671
    
    df.nums.map(ranges['index'])
    
    0    Q
    1    I
    2    R
    3    M
    4    M
    5    Q
    6    J
    7    K
    8    P
    9    Q
    

    【讨论】:

      猜你喜欢
      • 2022-10-15
      • 2012-08-21
      • 1970-01-01
      • 2012-09-16
      • 2023-04-05
      • 1970-01-01
      • 2011-04-20
      • 2022-01-03
      • 1970-01-01
      相关资源
      最近更新 更多