Python 突出显示基于多个条件的值

Python 突出显示基于多个条件的值,python,pandas,styles,Python,Pandas,Styles,我想对等于或超过指导值的值(单元格)进行着色处理(当前在字典中,键(化学符号):值(指导限值)。我希望它能够处理多组指导原则,并根据超出的最高值指导原则对单元格进行着色。下表显示了所需的输出,指导原则指定了颜色,每个指导原则的超出值指定了相同的颜色 这显示了三种不同指南(ANZECC、WHO和美国环境保护局)对铜、镉、SO4和锌的限值。结果如下(现场1-3),并根据其突出显示(如有)它们超过了指导原则。因此,对于第一个参数,Cu,场地2仅超过美国EPA值,因此为黄色阴影。场地1所有指导原则中最

我想对等于或超过指导值的值(单元格)进行着色处理(当前在字典中,键(化学符号):值(指导限值)。我希望它能够处理多组指导原则,并根据超出的最高值指导原则对单元格进行着色。下表显示了所需的输出,指导原则指定了颜色,每个指导原则的超出值指定了相同的颜色

这显示了三种不同指南(ANZECC、WHO和美国环境保护局)对铜、镉、SO4和锌的限值。结果如下(现场1-3),并根据其突出显示(如有)它们超过了指导原则。因此,对于第一个参数,Cu,场地2仅超过美国EPA值,因此为黄色阴影。场地1所有指导原则中最高的是WHO值,因此为蓝色阴影。场地3也超过了所有指导原则,最大值为WHO,因此为蓝色阴影。场地1的Cd超过美国EPA和ANZECC(两者相同)同样是绿色阴影(但可能是耶洛斯阴影,因为美国环境保护局的限制是相同的)。场地2没有超过任何指导方针,因此没有阴影。场地3超过所有指导方针,Cd的最高值是WHO,蓝色阴影也是。以此类推

我可以使用下面的代码根据一条准则对超标进行着色

#示例数据帧
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[3]:
镉铜铅硫酸盐锌
ANZECC_FW 0.0002 0.0014 0.0034 1000.0 0 0.008
澳新银行股票0.0100.4000 NaN 1000.0 20.000
CEPA_FW 0.0100 1.0000 0.0050 1000.05.000
然后对指南进行排序并指定颜色,包括:

fill_color={'ANZECC_FW':'blue',
"安排":"绿色",,
“ANZECC_股票”:“黄色”}
对于df.columns中的i:
col=df[i]
col=col.sort_值(升序=真)
#打印列,i,列idxmax()
#打印i
#打印颜色
计数=0
对于col中的val:
如果val>0:
打印i、val、列索引[计数],填充颜色[列索引[计数]]
计数+=1
其他:
持续
给出:


Cd 0.0002 ANZECC_FW蓝色
Cd 0.01 ANZECC_库存黄色
Cd 0.01 CEPA_FW绿色
铜0.0014 ANZECC_FW蓝色
Cu 0.4 ANZECC_库存黄色
Cu 1.0 CEPA_FW绿色
Pb 0.0034 ANZECC_FW蓝色
铅0.005 CEPA_FW绿色
硫酸盐1000.0 ANZECC_FW蓝色
硫酸盐1000.0 ANZECC_库存黄色
硫酸盐1000.0 CEPA_FW绿色
锌0.008 ANZECC_FW蓝
Zn 5.0 CEPA_FW绿色
锌20.0 ANZECC_库存黄色

所以我有了所有的信息,我只需要循环这些信息,以便数据中的每一列(如果单元格值>=列表值,指定填充颜色)都能正常工作,但我一直在思考如何应用这些信息。

看起来这就是你可以做到的:

编辑:

import pandas as pd, numpy as np
data=pd.DataFrame(({'Cd': [0.001,0.0005,1],'Cu':[0.004, 0.0017, 0.1],  'SO4': [700,450,1500],'Zn': [0.15,0.1,0.25],}))

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','ANZECC': 'red','US_EPA' :'yellow'}

def highlight(x):
  if x.name in guidelines.columns:
    style = []
    guide = guidelines[x.name]
    for i in x:
      condition = (guide<=i)
      _guide = guide[condition]
      try:
        match = _guide.index[np.argmax(np.array(_guide))]
        color = fill_color[match]
        style += [f"background-color: {color}"]
      except:
        style += ['']
    return style
  else:
    return ['']*len(x)

data.style.apply(highlight)
将熊猫作为pd导入,numpy作为np导入
data=pd.DataFrame({'Cd':[0.001,0.0005,1],'Cu':[0.004,0.0017,0.1],'SO4':[7004501500],'Zn':[0.15,0.1,0.25],}))
指南={'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},
‘美国环保署’:{'Cd':0.001,'Cu':0.0015,'SO4':500.0,'Zn':0.01}
}
指南=pd.DataFrame(指南).T
填充颜色={'WHO':'teal','ANZECC':'red','US_EPA':'yellow'}
def突出显示(x):
如果guidelines.columns中的x.name:
样式=[]
指南=指南[x.name]
对于x中的i:

条件=(指南首先,您的问题中有几个问题:

  • 您的数据不一致:为生成
    df
    而提供的代码包含一些混合了浮点数的字符串。如果您的数据中确实存在这种情况,那么您应该做的第一件事是将all转换为float:

    df=df.apply(pd.to_数值)

  • 您的
    指南在整个帖子中都会发生变化。例如:

  • 你从指导方针开始

    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}
    
    然后,稍后您将构建您的
    指南
    数据框架,您一定错误地将其命名为
    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}}
    
    这与前者完全不同


    也就是说,让我们根据您的图片建立一个新的
    指南
    填充颜色

    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)
    
    输出:


    限制的格式是什么?它是另一个数据框?或字典列表?是否可以像图片数据一样使用此格式编辑问题?@jezrael是否更好?是的,限制是字典。抱歉,很忙,但正在工作。没有相同值的首选项,可以作为指导原则。谢谢,这将创建一个新字典“大于条件”并将每一列与此进行比较,但每一列都有一个由“指南”字典定义的指南。不需要“大于条件”库。您的答案也对指南进行了着色,而不是对数据进行着色(问题中的第一个代码框)。如果引用了正确的词典,您的方法可能会起作用。是的,我想我错误地将指导原则假定为您的数据,因此,我添加了另一个
    dict
    ,以演示如何添加条件。让我在代码中添加df,并使用指导原则进行着色!谢谢,您能检查一下这一点吗,我在运行y时没有得到样式化的输出我们的代码。啊哈!您是否收到
    np.argmax
    (colab上没有显示)的错误?现在,已修复。谢谢。我确实指定了数据可能包含与赏金相关的注释中的NaN或空格。感谢您指出不一致之处,我将修复。您的代码返回错误:NameError:(“名称‘c’未定义)…很抱歉,错过了重构,
    c
    应该在
    return
    行中替换为
    s
    。修复了。如果输入数据的列不在指南中,这会很简单吗?是的,如果名称不在指南中,只需选中
    。列:return[']*len(col)
    对吗
    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)