根据多个条件突出显示值

时间:2020-05-12 07:36:20

标签: python pandas styles

我要遮盖等于或超过准则值(当前在词典中,键(化学符号):值(准则极限))的值(单元格),我希望它能够处理多组参考线,并根据被超过的最高值的参考线对单元格进行着色。下表显示了所需的输出,并为参考线分配了颜色,每条参考线的超出部分分配了相同的颜色。

enter image description here

这显示了针对铜,镉,二氧化硫和锌的三种不同指南(ANZECC,WHO和美国EPA)的限值。结果在下面(站点1 -3)下方,并根据超出的范围(如果有)进行突出显示。因此,对于第一个参数Cu,位置2仅超过US EPA值,因此阴影为黄色。站点1所有准则中,最高的准则是WHO值,因此阴影为蓝色。站点3也超出了所有准则,最大值是WHO,因此阴影也为蓝色。站点1的Cd超过了US EPA和ANZECC(相同),因此被涂成绿色(但由于US EPA限制相同,本来可以被涂成黄色)。站点2不超出任何准则,因此不要遮挡。站点3超出了所有指南,镉的最高含量是世界卫生组织,因此阴影为蓝色。等等。

我可以使用以下代码针对一项准则遮盖超出部分,

#example dataframe
df=pd.DataFrame(({'Cu':[0.004, 0.0017, 0.1],  'Cd': ['0.001','0.0005',1], 'SO4': [700,"450",1500],'Zn': ['0.15','0.1','0.25'],}))
cols=df.columns

给予

Out[7]:
      Cd      Cu   SO4    Zn
0   0.001  0.0040   700  0.15
1  0.0005  0.0017   450   0.1
2       1  0.1000  1500  0.25

#guideline values
WHO=  {'Cd' :0.002 ,'Cu' :0.003 ,'SO4':"NaN",'Zn' :0.1}
ANZECC=  {'Cd' :0.001 ,'Cu' :0.002 ,'SO4':1000.0,'Zn' :0.2}
US_EPA=  {'Cd' :0.001 ,'Cu' :0.0015 ,'SO4':500.0,'Zn' :0.01}

#highlight the relevant cells that are greater than the guideline
def fill_exceedances(x):
    color = 'orange'
    #get columns which are in keys of dict
    c = x.columns.intersection(ANZECC.keys())
    #filter columns and rename by dict
    df2 = x[c].rename(columns=ANZECC)
    #create boolean mask only for matched columns and compare
    mask = df2.astype(float).values < df2.columns[None,:].values
    #new DataFrame filled by no color
    df1 = pd.DataFrame('', index=x.index, columns=c)
    #set color by mask and add missing non matched columns names by reindex
    df1 = (df1.where(mask, 'background-color: {}'.format(color))
              .reindex(columns=x.columns, fill_value=''))

    return df1

df.style.apply(fill_exceedances, axis=None).to_excel('styled.xlsx', engine='openpyxl')

对于ANZECC指南,这给出了

enter image description here

我无法弄清楚如何应用连续样式,因为如果重复此过程,以前的样式会丢失。我觉得我走错了路,并且从最低准则到后续的连续样式都行不通。

更新:我将这些准则放入一本词典中,可以根据所使用的准则对其进行排序并指定颜色,但是我对如何进行操作感到困惑。

guidelines={"CEPA_FW":  {'Sulphate':1000,'Cd' :0.01 ,'Cu' :1.0 ,'Pb' :0.005 ,'Zn' :5.0}, 
 "ANZECC_Stock":{'Sulphate':1000,'Cd' :0.01,'Cu' :0.4, 'Zn' :20},
 "ANZECC_FW":  {'Sulphate':1000,'Cd' :0.0002 ,'Cu' :0.0014 ,'Pb' :0.0034 ,'Zn' :0.008}}


df=pd.DataFrame.from_records(guidelines).T
df

赠予:

Out[3]:
                  Cd      Cu      Pb  Sulphate      Zn
ANZECC_FW     0.0002  0.0014  0.0034    1000.0   0.008
ANZECC_Stock  0.0100  0.4000     NaN    1000.0  20.000
CEPA_FW       0.0100  1.0000  0.0050    1000.0   5.000

然后使用以下方法对准则进行排序并分配颜色:

fill_color={'ANZECC_FW':'blue',
'CEPA_FW' :'green',
'ANZECC_Stock': 'yellow'}

for i in df.columns:
    col=df[i]
    col=col.sort_values(ascending=True)
    #print col,i, col.idxmax()
    #print i
    #print col
    count=0
    for val in col:

        if val>0:

            print i,val,col.index[count],fill_color[col.index[count]]

            count+=1
        else:
            continue

礼物:


Cd 0.0002 ANZECC_FW blue
Cd 0.01 ANZECC_Stock yellow
Cd 0.01 CEPA_FW green
Cu 0.0014 ANZECC_FW blue
Cu 0.4 ANZECC_Stock yellow
Cu 1.0 CEPA_FW green
Pb 0.0034 ANZECC_FW blue
Pb 0.005 CEPA_FW green
Sulphate 1000.0 ANZECC_FW blue
Sulphate 1000.0 ANZECC_Stock yellow
Sulphate 1000.0 CEPA_FW green
Zn 0.008 ANZECC_FW blue
Zn 5.0 CEPA_FW green
Zn 20.0 ANZECC_Stock yellow

所以我拥有所有信息,我只需要遍历这些信息,以便数据中的每一列(如果单元格值> =列表值,则指定填充颜色)就可以正常工作,但我仍然坚持如何应用这个。

2 个答案:

答案 0 :(得分:2)

首先,您的问题很少:

  1. 您的数据不一致:用于生成df的代码包含一些混合了浮点数的字符串。如果您的数据确实是这种情况,那么您应该做的第一件事就是将所有内容都转换为float:

    df = df.apply(pd.to_numeric)

  2. 您在整个帖子中的guidelines更改。例如:

您从准则开始

WHO=  {'Cd' :0.002 ,'Cu' :0.003 ,'SO4':"NaN,'Zn' :0.1}       # string `NaN` again?
ANZECC=  {'Cd' :0.001 ,'Cu' :0.002 ,'SO4':1000.0,'Zn' :0.2}
US_EPA=  {'Cd' :0.001 ,'Cu' :0.0015 ,'SO4':500.0,'Zn' :0.01}

然后,稍后再构建您的guidelines数据框,您也必须错误地将其命名为df,如下:

# no string `NaN`
# Sulphate or SO4
# different standard names
guidelines={"CEPA_FW":  {'Sulphate':1000,'Cd' :0.01 ,'Cu' :1.0 ,'Pb' :0.005 ,'Zn' :5.0}, 
 "ANZECC_Stock":{'Sulphate':1000,'Cd' :0.01,'Cu' :0.4, 'Zn' :20},
 "ANZECC_FW":  {'Sulphate':1000,'Cd' :0.0002 ,'Cu' :0.0014 ,'Pb' :0.0034 ,'Zn' :0.008}}

这与前者完全不同。


也就是说,让我们根据您的图片来构建新的guidelinesfill_color

guidelines = {'WHO' :  {'Cd' :0.002 ,'Cu' :0.003 ,'SO4':np.NaN,'Zn' :0.1},
              'ANZECC' : {'Cd' :0.001 ,'Cu' :0.002 ,'SO4':1000.0,'Zn' :0.2},
              'US_EPA' :  {'Cd' :0.001 ,'Cu' :0.0015 ,'SO4':500.0,'Zn' :0.01}
              }
guidelines = pd.DataFrame(guidelines).T

fill_color = {'WHO':'teal',
              'US_EPA' :'yellow',
              'ANZECC': 'green'}

函数如下:

def hightlight(col):
    name = col.name

    # extract the threshold and sort decreasingly
    thresh = guidelines[name].sort_values(ascending=False)

    # compare each value in column to each threshold
    compare = np.greater_equal.outer(col.values, thresh.values)

    # if any threshold is exceeded
    exceed_thresh = compare.any(1)

    # and where it is exceeded
    exceed_idx = np.argmax(compare, axis=1)

    # extract the standards that has is passed
    standards = np.where(exceed_thresh, thresh.index[exceed_idx], '')

    # format strings
    return [f'background-color:{fill_color[s]}' if s else '' for s in standards ]

df.style.apply(hightlight)

输出:

enter image description here

答案 1 :(得分:1)

看来这是您可以采取的方法:

编辑:

;; With 
(defun add (x y) (+ x y))

(defun mul (x y) (* x y))

;; I want to have this:
(let-curry 1000 (add mul)
  (print (add 3))
  (print (mul 3)))


;; expanding to:
(flet ((add (y) (add 1000 y))
       (mul (y) (mul 1000 y)))
  (print (add 3))
  (print (mul 3)))

;; but instead I'm getting:
Execution of a form compiled with errors.
Form:
  (FLET (LOOP
       FOR
       #1=#:G777
       IN
       (ADD MUL
         )
       COLLECT
       (LIST #1#
         (&REST ARGS)
         (FUNCALL #1# 1000 ARGS)))
  (PRINT (ADD 3))
  (PRINT (MUL 3)))
Compile-time error:
  The FLET definition spec LOOP is malformed.
   [Condition of type SB-INT:COMPILED-PROGRAM-ERROR]

看起来像这样(您可以继续添加其他格式/更改颜色等): pandas styling

相关问题