【问题标题】:Descriptive statistics in Python /with Pandas with std in parenthesesPython 中的描述性统计数据 / 使用 Pandas,括号中为 std
【发布时间】:2019-06-25 05:53:27
【问题描述】:

此问题涉及在 Python 中使用与学术出版物中的表格相对应的格式化输出进行描述性统计的最佳实践:表示其各自的标准偏差在下面的括号中。最终目标是能够以 Latex 表格格式(或其他格式、html 等)导出它。

示例 (Deucherta & Eugster (2018)):

熊猫:

在 Pandas 中进行描述性统计的经典解决方案是使用 DataFramedescribe() 方法。

import numpy as np
import pandas as pd 

# Generate a DataFrame to have an example 
df = pd.DataFrame(
    {"Age" : np.random.normal(20,15,5), 
     "Income": np.random.pareto(1,5)*20_000 }
    )
# The describe method to get means and stds
df.describe().loc[["mean", "std"]].T
>>>
                mean            std
Age        15.322797      13.449727
Income  97755.733510  143683.686484

我想要的是以下输出:

Age        15.32 
          (13.44)
Income  97755.73  
        (143683.68)

如果有一个适用于多索引数据框的解决方案会很好:

df2 = pd.DataFrame(
    {"Age" : np.random.normal(20,15,5), 
     "Income": np.random.pareto(1,5)*20_000 }
    )
df_c = pd.concat([df,df2], keys = ["A", "B"])
>>>

得到

                A           B
Age          23.15       21.33
            (11.62)      (9.34)
Income    68415.53    46619.51
         (95612.40)  (64596.10)

我目前的解决方案:

idx = pd.IndexSlice
df_desc = (df_c
      ).groupby(level = 0, axis = 0).describe()
df_desc = df_desc.loc[idx[:],idx[:,["mean", "std"]]].T
df_desc.loc[idx[:,["std"]],idx[:]] = df_desc.loc[idx[:,["std"]],idx[:]
                                               ].applymap(
                                               lambda x: "("+"{:.2f}".format(x)+")")
print(df_desc)

>>>
                     A           B
Age    mean     23.1565     21.3359
      std      (11.62)      (9.34)
Income mean     68415.5     46619.5
      std   (95612.40)  (64596.10)
问题1:

我没有找到隐藏第二个索引列 [mean, std, mean,std] 的解决方案。

然后我想将我的 df 导出到乳胶:

df_desc.to_latex()

>>>
\begin{tabular}{llll}
\toprule
       &     &            A &           B \\
\midrule
Age & mean &       5.5905 &     29.5894 \\
       & std &      (16.41) &     (13.03) \\
Income & mean &       531970 &     72653.7 \\
       & std &  (875272.44) &  (79690.18) \\
\bottomrule
\end{tabular}
问题2:

表格的 & 字符未对齐,这使得编辑有点乏味(我在 VSCode 中使用扩展来对齐 &

总的来说,我觉得这个解决方案乏味且不优雅。

解决方案?

如果没有复杂的字符串操作,我不知道我应该怎么做才能获得所需的结果。

我看过Pandas styling,但我不认为这是最好的解决方案。

还有StatModels Tables,但是我没有找到简单的解决我的问题的方法。 Statsmodels Tables 似乎是最有希望的解决方案。但我不知道如何实现它。 StatsModels 中有一些描述性的统计函数,但我在 GitHub 上读到它们在某种程度上已被弃用。

那么制作这些表格的最佳方法是什么?

【问题讨论】:

    标签: python pandas statistics statsmodels standard-deviation


    【解决方案1】:

    我刚刚遇到了类似的问题,发现了你的帖子,所以我是这样处理你提到的问题的。

    问题一:隐藏第二个索引列

    我更喜欢解决方案 b),但出于说明目的将 a) 留在这里。

    a) droplevel & set_index

    df_desc.index.droplevel(level=1)
    
    >>>
    Index(['Age', 'Age', 'Income', 'Income'], dtype='object')
    

    将这段代码与set_index 表达式一起使用:

    df_desc.set_index(df_desc.index.droplevel(level=1), inplace=True)
    

    这会导致:

    print(df_desc)
    
    >>>
                      A           B
    Age         17.1527     23.9678
    Age         (19.73)     (12.01)
    Income       293271     12178.8
    Income  (400059.27)  (14483.35)
    

    这看起来还不令人满意,因为索引值 AgeIncome 分别出现了两次。

    这就是我想出以下内容的原因。

    b) 使用 pd.DataFrame.values 创建新的 DataFrame 并手动分配索引

    首先,重置索引:

    df_desc = df_desc.reset_index(drop=True)
    
    print(df_desc)
    
    >>>
                A           B
    0      17.306      11.425
    1     (14.40)     (16.67)
    2     88016.7     67280.4
    3  (73054.44)  (54953.69)
    

    其次,手动创建新的 DataFrame 指定索引和列名。 请注意,我使用df_desc.values 作为数据参数(第一个位置)。

    df_new = pd.DataFrame(df_desc.values, index=["Age", "", "Income", ""], columns=["A", "B"])
    
    print(df_new)
    
    >>>
                     A           B
    Age        27.7039     20.8031
               (13.99)     (13.92)
    Income     20690.7     7370.44
            (29470.03)  (13279.10)
    

    问题2:对齐LaTeX表格

    注意运行

    df_new.to_latex()
    

    确实会产生一些混乱的str 输出:

    >>> 
    '\\begin{tabular}{lll}\n\\toprule\n{} &           A &           B \\\\\n\\midrule\nAge    &     27.7039 &     20.8031 \\\\\n       &     (13.99) &     (13.92) \\\\\nIncome &     20690.7 &     7370.44 \\\\\n       &  (29470.03) &  (13279.10) \\\\\n\\bottomrule\n\\end{tabular}\n'
    

    但是,将其包装在 print 语句中会产生所需的输出:

    print(df_new.to_latex())
    
    >>>
    \begin{tabular}{lll}
    \toprule
    {} &           A &           B \\
    \midrule
    Age    &     27.7039 &     20.8031 \\
           &     (13.99) &     (13.92) \\
    Income &     20690.7 &     7370.44 \\
           &  (29470.03) &  (13279.10) \\
    \bottomrule
    \end{tabular}
    

    此外,将表格导出到 LaTeX 文档相当简单。

    正如您自己所指出的,to_latex() 已经创建了一个表格,因此您只需将其写入一个文件,并在您的 LaTeX 文档中使用\input。 按照示例here,执行以下操作:

    i) 将表格另存为文本文件

    with open('mytable.tex','w') as tf:
        tf.write(df_new.to_latex())
    

    ii) 在 LaTeX 文档中使用导出的表格

    \documentclass{article}
    \usepackage{booktabs}
    \begin{document}
    \input{mytable}
    \end{document}
    

    这里的示例假设mytable.tex 和LaTeX 文档在同一个文件夹中。 booktabs 包是必需的,因为to_latex() 使用booktabs 命令来生成表规则。

    最终的 pdf 输出如下所示:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-13
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-08
      • 1970-01-01
      相关资源
      最近更新 更多