Pandas:当密钥与容差匹配时,通过字典值更改数据框列中的值

时间:2016-11-30 04:56:04

标签: python pandas dictionary dataframe iteration

因此,当键位于[value-tolerance,value + tolerance]对应的范围内时,我想用字典中的字符串替换Dataframe列中的值。

例如这样的词典:

dict = {101.2:"A", 110:"A", 150:"B", 170:"C", 600:"A"}

我想替换“aa”列中的值,如果此值在一个或多或少的容差范围内与字典中的键匹配相应的字符串值。

作为下面的例子我希望“aa”列中的值101与字典中的键101.2匹配,如果我将容差值设置为0.5,从而将值101更改为“A”以匹配列“aa”中的行”

这是一个例子:

     end  start  diff   aa
0   200     99   101  101
1   250     99   151  151
2   270     99   170.2  170.2
3   300     99   201  201
4   450     99   351  351
5   600     99   501  501
6   800     99   701  701
7   250    200    50   50
8   270    200    70   70
9   300    200   100  100
10  450    200   250  250
11  600    200   400  400
12  800    200   600  600
13  270    250    20   20
14  300    250    50   50
15  450    250   200  200
16  600    250   350  350
17  800    250   550  550
18  300    270    30   30
19  450    270   180  180
20  600    270   330  330
21  800    270   530  530
22  450    300   150  150
23  600    300   300  300
24  800    300   500  500
25  600    450   150  150
26  800    450   350  350
27  800    600   200  200

从剪贴板加载数据框

table = pd.read_clipboard().iloc[1:]
tol_value = 0.5

预期结果:

     end  start  diff   aa
0   200     99   101   A
1   250     99   151   151
2   270     99   170.2 C
3   300     99   201   201
4   450     99   351   351
5   600     99   501   501
6   800     99   701   701
7   250    200    50    50
8   270    200    70    70
9   300    200   100   100
10  450    200   250   250
11  600    200   400   400
12  800    200   600   600
13  270    250    20    20
14  300    250    50    50
15  450    250   200   200
16  600    250   350   350
17  800    250   550   550
18  300    270    30    30
19  450    270   180   180
20  600    270   330   330
21  800    270   530   530
22  450    300   150   B
23  600    300   300   300
24  800    300   500   500
25  600    450   150   B
26  800    450   350   350
27  800    600   200   200

我知道如何用以下完全匹配替换:

table2 = table.replace({"aa": dict})

但我无法弄清楚如何以宽容度做同样的事情。

我试过了:

for index, row in table.iterrows():
    for key, value in dict.iteritems():
        if (row['aa']-tol_value <= key) & (key <= row['aa']+tol_value):
            table.replace(row.aa, value)

它可以工作但不幸的是,这会产生与迭代一样多的数据帧。

非常感谢任何帮助

1 个答案:

答案 0 :(得分:2)

供您参考:

创建一个新的dict来存储您的参考资料

dict = {101.2: 'A', 110: 'A', 150: 'B', 170: 'C', 600: 'A'}

def new_dict(dict):
    new_dict={}
    for i,j in dict.items():
        if j not in new_dict.keys():
            new_dict[j] = [i]
        else:
            new_dict[j].append(i)
    return new_dict

new = new_dict(dict)
  

     

{'A':[600,101.2,110],'B':[150],'C':[170]}

使用新词典拟合数据

def fit(x, dict, tol):
    for key in dict.keys():  
        for item in dict[key]: # There are many items in a key
            if (x > item-tol) and ( x <= item+tol):
                return key
    return x

将功能应用于您的数据

table.aa = table.aa.apply(lambda x: fit(x, new, 0.5))

明白了

    end start   diff    aa
0   200 99  101.0   A
1   250 99  151.0   151
2   270 99  170.2   C
3   300 99  201.0   201
4   450 99  351.0   351
5   600 99  501.0   501
6   800 99  701.0   701
7   250 200 50.0    50
8   270 200 70.0    70
9   300 200 100.0   100
10  450 200 250.0   250
11  600 200 400.0   400
12  800 200 600.0   A
13  270 250 20.0    20
14  300 250 50.0    50
15  450 250 200.0   200
16  600 250 350.0   350
17  800 250 550.0   550
18  300 270 30.0    30
19  450 270 180.0   180
20  600 270 330.0   330
21  800 270 530.0   530
22  450 300 150.0   B
23  600 300 300.0   300
24  800 300 500.0   500
25  600 450 150.0   B
26  800 450 350.0   350
27  800 600 200.0   200