使用 pandas 和复杂条件绘制单元格
Painting cells using pandas and complex conditions
我有一个数据框,其中包含几种化学元素的标准差、平均值和中值。示例数据:
test = pd.DataFrame({('Na', 'std'):{'A': 1.73, 'B':0.95, 'C':2.95}, ('Na', 'mean'):{'A': 10.3, 'B':11, 'C':20}, ('Na', 'median'):{'A':11, 'B':22, 'C':34},('K', 'std'):{'A': 1.33, 'B':1.95, 'C':2.66}, ('K', 'mean'):{'A': 220.3, 'B':121, 'C':290}, ('K', 'median'):{'A':211, 'B':122, 'C':340}})
table 示例:
Na K
std mean med std mean med
A 1.73 10.3 11 1.33 220.3 211
B 0.95 11.0 22 1.95 121.0 122
C 2.95 20.0 34 2.66 290.0 340
我想按照特定条件绘制单元格:
- 我想为每个化学元素的 std 列中的两个最小值着色(示例:Na 为 0.95 和 1.73,K 为 1.33 和 1.95);
- 我想根据函数 [abs(mean - median)] 的两个最小值为所有元素(示例:(10.3, 11) 和 (11.0, 22) ) 对于 Na,以及 (220.3, 211) 和 (121, 122) 对于 K)。
我做了这些函数来按照我想要的条件识别要绘制的单元格的值,但我不知道如何在pd.style函数中实现它们。
def paint1(test):
val_keep = []
for element,stats in test:
if stats == 'std':
paint1 = test[element].nsmallest(2, 'std')
for value in paint1['std']:
val_keep.append(value)
return val_keep
def paint2(test):
val_keep = []
for element,stats in test:
if stats == 'mean':
diff = abs(test[element]['mean'] - test[element]['median'])
paint2 = diff.nsmallest(2).index
for value in paint2:
val_keep.append((test[element]['mean'][value]))
val_keep.append(test[element]['median'][value])
return val_keep
如何使用这些条件绘制单元格?我看到其他 posts 使用 lambda 函数来定义样式,但我认为我需要的函数比那更复杂。
使用df.style
:
def styler(col):
chem, stat = col.name
if stat == 'std':
return np.where(col.isin(col.nsmallest(2)), 'color: red', '')
elif stat in ['mean', 'median']:
delta = (df[(chem, 'mean')] - df[(chem, 'median')]).abs()
return np.where(delta.isin(delta.nsmallest(2)), 'color: blue', '')
else:
return [''] * len(col)
df.style.apply(styler)
我有一个数据框,其中包含几种化学元素的标准差、平均值和中值。示例数据:
test = pd.DataFrame({('Na', 'std'):{'A': 1.73, 'B':0.95, 'C':2.95}, ('Na', 'mean'):{'A': 10.3, 'B':11, 'C':20}, ('Na', 'median'):{'A':11, 'B':22, 'C':34},('K', 'std'):{'A': 1.33, 'B':1.95, 'C':2.66}, ('K', 'mean'):{'A': 220.3, 'B':121, 'C':290}, ('K', 'median'):{'A':211, 'B':122, 'C':340}})
table 示例:
Na K
std mean med std mean med
A 1.73 10.3 11 1.33 220.3 211
B 0.95 11.0 22 1.95 121.0 122
C 2.95 20.0 34 2.66 290.0 340
我想按照特定条件绘制单元格:
- 我想为每个化学元素的 std 列中的两个最小值着色(示例:Na 为 0.95 和 1.73,K 为 1.33 和 1.95);
- 我想根据函数 [abs(mean - median)] 的两个最小值为所有元素(示例:(10.3, 11) 和 (11.0, 22) ) 对于 Na,以及 (220.3, 211) 和 (121, 122) 对于 K)。
我做了这些函数来按照我想要的条件识别要绘制的单元格的值,但我不知道如何在pd.style函数中实现它们。
def paint1(test):
val_keep = []
for element,stats in test:
if stats == 'std':
paint1 = test[element].nsmallest(2, 'std')
for value in paint1['std']:
val_keep.append(value)
return val_keep
def paint2(test):
val_keep = []
for element,stats in test:
if stats == 'mean':
diff = abs(test[element]['mean'] - test[element]['median'])
paint2 = diff.nsmallest(2).index
for value in paint2:
val_keep.append((test[element]['mean'][value]))
val_keep.append(test[element]['median'][value])
return val_keep
如何使用这些条件绘制单元格?我看到其他 posts 使用 lambda 函数来定义样式,但我认为我需要的函数比那更复杂。
使用df.style
:
def styler(col):
chem, stat = col.name
if stat == 'std':
return np.where(col.isin(col.nsmallest(2)), 'color: red', '')
elif stat in ['mean', 'median']:
delta = (df[(chem, 'mean')] - df[(chem, 'median')]).abs()
return np.where(delta.isin(delta.nsmallest(2)), 'color: blue', '')
else:
return [''] * len(col)
df.style.apply(styler)