Pandas 基于 NaN 值的数据框颜色样式

Pandas Dataframe Color Styling based on NaN Values

我目前有一个 pandas 数据框,它有四列,结构如下。

| Date        | Transaction ID | Amount 1 | Amount 2 
| Nov-10-2021 | ABC123         | 100.20   | nan
| Dec-10-2021 | DEF456         | nan      | 30.21
| Dec-13-2021 | GHI789         | 341.88   | nan
| Dec-18-2021 | JKL101         | nan      | 122.3            

如您所见,这是一个交易数据框。我想将被视为“收入”的交易行着色为“黄色”,将被视为“费用”的交易行着色为“绿色”。为此,如果金额 1 为 nan,则该行为收入行,否则为费用。在阅读 pandas 颜色样式文档和其他 Stack Overflow 帖子后,我尝试了以下操作:

def yellow_or_green(dataframe):
    if (pd.isna(dataframe["Amount 1"])):
        color = "yellow"
    else:
        color = "green"
    return "color: %s" % color

df1.style.applymap(yellow_or_green)

然后,显示dataframe后,它保持不变。我不确定为什么它不起作用,感谢您的帮助和指导。

使用:

df = pd.DataFrame({'Date': ['Nov-10-2021', 'Dec-10-2021', 'Dec-13-2021', 'Dec-18-2021'], 
                   'Transaction ID': ['ABC123', 'DEF456', 'GHI789', 'JKL101'], 
                   'Amount 1': [100.2, np.nan, 341.88, np.nan],
                   'Amount 2': [ np.nan, 30.21,  np.nan, 122.3]})
    

print (df)

          Date Transaction ID  Amount 1  Amount 2
0  Nov-10-2021         ABC123    100.20       NaN
1  Dec-10-2021         DEF456       NaN     30.21
2  Dec-13-2021         GHI789    341.88       NaN
3  Dec-18-2021         JKL101       NaN    122.30

print (df.columns.tolist())
['Date', 'Transaction ID', 'Amount 1', 'Amount 2']

def yellow_or_green(x):
    c1 = 'background-color: yellow'
    c2 = 'background-color: green'
    # condition
    m = x["Amount 1"].isna()
    # DataFrame of styles
    df1 = pd.DataFrame(c1, index=x.index, columns=x.columns)

    # set columns by condition
    return df1.mask(m, c2)

#if not working convert to numeric
df["Amount 1"] = df["Amount 1"].astype(float)
#then try convert with NaNs for non parseable values
df["Amount 1"] = pd.to_numeric(df["Amount 1"], errors='coerce')

df.style.apply(yellow_or_green, axis=None).to_excel('styled.xlsx', engine='openpyxl')

如果只需要对某些列进行着色:

def yellow_or_green(x):
    c1 = 'background-color: yellow'
    c2 = 'background-color: green'
    # condition
    m = x["Amount 1"].isna()
    # DataFrame of styles
    df1 = pd.DataFrame('', index=x.index, columns=x.columns)
    df1.loc[:, ['Date','Transaction ID']] = np.where(m.to_numpy()[:, None], c1, c2)
    # set columns by condition
    return df1

df.style.apply(yellow_or_green, axis=None).to_excel('styled.xlsx', engine='openpyxl')