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)
我一直在研究如何将预先存在的样式选项 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
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)