4

我有一个pandas.DataFramewith 值,说:

df = pd.DataFrame(np.random.randn(5, 3), columns=['a', 'b', 'c'])

In [160]: df
Out[160]:
          a         b         c
0 -0.316527 -0.721590  1.812285
1 -1.704653 -0.415888 -0.294740
2 -1.126637  0.032084 -1.344484
3  0.081789 -1.311954  1.941496
4  0.617405  0.114212 -0.763610

现在我已经编写了自己的颜色渐变函数,以便获得pd.DataFrame相同大小和形状的 a,但每个单元格都有颜色十六进制代码,例如:

df_clrs = pd.DataFrame([
    ['#bc4700', '#dea380', '#bc4700'], 
    ['#384f69', '#dea380', '#bc4700'], 
    ['#dea380', '#bc4700', '#384f69'], 
    ['#384f69', '#384f69', '#dea380'],
    ['#dea380', '#bc4700', '#384f69']], 
    columns=['a', 'b', 'c']
)

In [164]: df_clrs
Out[164]:
         a        b        c
0  #bc4700  #dea380  #bc4700
1  #384f69  #dea380  #bc4700
2  #dea380  #bc4700  #384f69
3  #384f69  #384f69  #dea380
4  #dea380  #bc4700  #384f69

我假设我也用文本颜色做到了这一点,所以:

 df_fnts = pd.DataFrame([
    ['#f1f1f1','#f1f1f1','#000000'],
    ['#000000','#f1f1f1','#f1f1f1'],
    ['#000000','#f1f1f1','#000000'],
    ['#f1f1f1','#000000','#f1f1f1'],
    ['#000000','#000000','#f1f1f1']],
    columns=['a', 'b' ,'c']
)

In [167]: df_fnts
Out[167]:
         a        b        c
0  #f1f1f1  #f1f1f1  #000000
1  #000000  #f1f1f1  #f1f1f1
2  #000000  #f1f1f1  #000000
3  #f1f1f1  #000000  #f1f1f1
4  #000000  #000000  #f1f1f1

我的目标是现在公开DatFrame.style功能,如这些教程中所示。

但是,教程中演示的所有函数都侧重于传递函数(使用pd.DataFrame.style.applymap),但是,我已经创建了所有属性。

我尝试过的事情

因为在文档中看起来您需要使用适当的属性附加值,所以我创建了一个这样的函数:

def _apply_prop(df, prop):
   return df.applymap(lambda x: prop + ':' + x)

# apply the color mapping
df.style.applymap(
    _apply_prop(
        df_clrs, 
       'background-color'
    )
).to_excel('~/Desktop/background-colors.xlsx')

但我得到一个TypeError

TypeError: the first argument must be callable
4

3 回答 3

3

df(5x3) 和df_clrs(4x3) 具有不同的形状。假设你得到了纠正,试试这个:

def _apply_prop(_, style, prop):
    return style.applymap(lambda x: prop + ':' + x)

df.style.apply(_apply_prop, axis=None, style=df_clrs, prop='background-color')

输出:

样式化数据框

一些注意事项:

  • 不要打电话style.applymap。它遍历单元格。用于apply(..., axis=...)迭代列/行/表。无论您迭代什么,都返回一个具有相同形状的对象。
  • 您不会在apply / applymap. 您提供函数的名称及其参数
  • 样式函数的第一个参数始终是被样式化的数据框。apply / applymap隐式地将数据框传递给样式函数。您可以通过关键字传递其他参数。
于 2019-07-23T22:40:08.007 回答
0

我知道这不是您想要的,但它确实成功地将颜色应用于 df_clrs DataFrame

def apply_prop(val):
    return 'color: %s' % val
df_clrs.style.applymap(apply_prop)

applymap 只能将函数作为对象除外。因此,您将无法向函数添加参数。

请记住,样式的想法是根据正在设置样式的数据框中的数据进行样式设置。不是另一个 DataFrame。

于 2019-07-23T19:37:21.677 回答
0

我最终想出了一个不同的解决方案:

  1. 避免使用applymap(我记得应用到所有元素是一个较慢的操作)
  2. 利用函数中的“列名”apply来引用样式矩阵的相应列。
def _apply_format(srs, df, prop):
    """
    Parameters
    ----------
    srs : :class:`Series`
        This is the column that will be passed automatically in the `apply` function
    df : :class:`DataFrame`
        The matrix of styling attributes with the same shape as the matrix to be styled
    prop : str
        The property to style, e.g. 'background-color'
    """
    nm  = srs.name
    row = df[nm]
    return (prop + ': ' + row).tolist()

现在我可以将背景颜色和字体颜色的样式功能链接在一起,如下所示:

(df.style.
         apply(_apply_format, axis=0, subset=subset, **{'df': df_clrs, 'prop': 'background-color'}).
         apply(_apply_format, axis=0, subset=subset, **{'df': df_fnts, 'prop': 'color'}).
         to_excel('~/Desktop/pretty-table.xlsx', engine='openpyxl')
     )

在此处输入图像描述

于 2019-07-24T13:42:54.763 回答