Python: dataframe styler 的简单映射

Python: simple mapping of dataframe styler

我一直在研究如何将预先存在的样式选项 df 映射到整数 df:

import numpy as np
import pandas as pd

# Create a 9 x 3 array of integers
random_state = np.random.RandomState(seed=44)
myArray = random_state.randint(0,9, (9,3))

给出输出:

[[4 3 1]
 [3 0 4]
 [3 8 7]
 [7 6 3]
 [7 3 3]
 [6 5 4]
 [5 1 8]
 [7 4 5]
 [3 0 4]]

然后创建一个 'color: option' 的随机 2D 列表,以使用样式器映射到 myArray:

styleList    = []
colorOptions = ['color: lime','color: red','color: yellow']

for i in arr:
  inner = []
  for j in i:
    inner.append(np.random.choice(colorOptions))
  styleList.append(inner)

for i in styleList: print(i)

检查输出:

['color: yellow', 'color: lime'  , 'color: red']
['color: red'   , 'color: lime'  , 'color: red']
['color: yellow', 'color: yellow', 'color: yellow']
['color: yellow', 'color: red'   , 'color: lime']
['color: yellow', 'color: red'   , 'color: yellow']
['color: red'   , 'color: lime'  , 'color: yellow']
['color: red'   , 'color: yellow', 'color: red']
['color: yellow', 'color: yellow', 'color: yellow']
['color: lime'  , 'color: red'   , 'color: red']

将这两个转换为数据帧:

df      = pd.DataFrame(data=myArray,   index=None, columns=['col1', 'col2', 'col3'])
dfStyle = pd.DataFrame(data=styleList, index=None, columns=['col1', 'col2', 'col3'])

因为我已经有了带有样式选项的数据框 dfStyle我怎样才能简单地将它的值映射到 df 中的整数值(以及而不必在单独的函数中生成 dfStyle)?

我会避免使用 df.style.apply()df.style.applymap() 甚至尝试简单地 return dfStyle 的各种函数来使这个 space 混乱。但是这个看似简单的任务让我陷入了困境。

期望的结果是样式化的 df:

df[0][0]应该是黄色显示的数字4

df[0][1] 应该是用颜色 lime

显示的数字 3

df[0][2]应该是用红色显示的数字1

等等

感谢您的帮助。

••• 更新•••

我想出了如何根据需要正确映射样式的方法:

def color(row):
  dfs = dfStyle.copy()
  x = [dfs.iloc[row.name][j] for i,j in zip(row, dfStyle)]
  return x

df.style.apply(color, axis=1)

结果是:

正如我在问题末尾发布的那样,我设法通过以下方式找到了我想要的解决方案:

def color(row):
  dfs = dfStyle.copy()
  x = [dfs.iloc[row.name][j] for i,j in zip(row, dfStyle)]
  return x

df.style.apply(color, axis=1)

虽然这确实是我想要的解决方案,但它似乎是一种相当复杂且不必要的复杂方法。

如果知道一种简单直观的方法来实现同样的目标,我将不胜感激。

在反复研究我复杂的解决方案之后,我得出了以下(更清晰的)解决方案来解决我的原始问题。

我无法在 SO 的其他地方找到这些,所以对于其他感兴趣的人:

解决方案使用apply(axis=0)

def f1(col): return [ dfStyle[col.name][i] for i in range(len(dfStyle)) ]

df.style.apply(f1, axis=0)

通过列表理解

使用applymap()的解决方案
styleIterator = iter([ row for col in dfStyle for row in dfStyle[col] ] )

def f1(x): return next(styleIterator)

df.style.applymap(f1)

通过built-in函数使用applymap()的解决方案

styleIterator = iter(dfStyle.values.flatten(order='F').tolist() )

# OR

styleIterator = iter(dfStyle.to_numpy().flatten(order='F').tolist() )

def f1(x): return next(styleIterator)

df.style.applymap(f1)

并且,根据朋友的提供,使用 apply(axis=1) 和 lambda

的解决方案
color = lambda row: [dfStyle.iloc[row.name][col] for col in dfStyle]

df.style.apply(color, axis=1)