【问题标题】:Add df under other df Pandas在其他 df Pandas 下添加 df
【发布时间】:2022-11-04 12:49:08
【问题描述】:

我正在使用 for 生成一个 excel 文件来绘制来自 df 的数据,所以我使用 value_counts 但我想在这个 df 下添加第二个具有相同数据但百分比的文件,所以我的代码是这个:

li = []

for i in range(0, len(df.columns)):
    value_counts = df.iloc[:, i].value_counts().to_frame().reset_index()
    value_percentage = df.iloc[:, i].value_counts(normalize=True).to_frame().reset_index()#.drop(columns='index')
    value_percentage = (value_percentage*100).astype(str)+'%'
    li.append(value_counts)
    li.append(value_percentage)
data = pd.concat(li, axis=1)
data.to_excel("resultdf.xlsx") #index cleaned

基本上我需要它看起来像这样:

【问题讨论】:

    标签: python pandas dataframe append


    【解决方案1】:

    只要两个数据帧之间的列名匹配,您就应该能够使用pd.concat() 连接两个数据帧。要垂直连接它们,我认为您应该使用 axis=0 而不是 axis=1 see docs

    【讨论】:

      【解决方案2】:

      数据

      让我们准备一些虚拟数据来处理。根据提供的屏幕截图,我假设原始数据是音乐流派等级,等级为 1 到 5。所以我将使用如下数据:

      import pandas as pd
      from numpy.random import default_rng
      
      rng = default_rng(0)
      columns = ['Pop', 'Dance', 'Rock', 'Jazz']
      data = rng.integers(1, 5, size=(100, len(columns)), endpoint=True)
      
      df = pd.DataFrame(data, columns=columns)
      

      原始代码注释

      1. 无需按列索引进行迭代。我们可以遍历列名,如for column in df.columns: df[column] ...
      2. 我认为在将它们转换为帧之前,最好在map('.0%'.format) 的帮助下格式化数据。
      3. 我们最好pd.concat 将它们垂直添加到单个帧中并将其附加到列表中,而不是一个一个地附加计数值和标准化值。

        所以原来的代码可以改写成这样:

        li = []
        
        for col in df.columns:
            value_counts = df[col].value_counts()
            value_percentage = df[col].value_counts(normalize=True).map('{:.0%}'.format)
            li.append(pd.concat([value_counts, value_percentage]).to_frame().reset_index())
        
        resultdf = pd.concat(li, axis=1)
        resultdf.to_excel("resultdf.xlsx") 
        

        让 Excel 进行格式化

        如果我们让 Excel 自己将数据格式化为百分比会怎样?我认为最简单的方法是使用Styler。但在此之前,我建议摆脱Index 列。正如我所看到的,它们都指的是相同的等级1,2,3,4,5。因此我们可以将它们用作公共索引,从而使索引有意义。此外,我将使用MultiIndex 来分隔计数值和标准化值,如下所示:

        formula = ['counts', 'percent']
        values = [1, 2, 3, 4, 5]
        counted = pd.DataFrame(index=pd.MultiIndex.from_product([formula, values], names=['formula', 'values']))
        

        counted 是我们的数据容器,目前它是空的。让我们填写:

        for col in df.columns:
            counts = df[col].value_counts()
            percent = counts / counts.sum()
            counted[col] = pd.concat([counts, percent], keys=formula)
        

        有了这些数据,让我们对它们应用一些样式,然后再转换成 Excel 文件:

        styled_data = (
            counted.style
            .set_properties(**{'number-format': '0'}, subset=pd.IndexSlice['counts', columns])
            .set_properties(**{'number-format': '0%'}, subset=pd.IndexSlice['percent', columns])
        )
        styled_data.to_excel('test.xlsx')
        

        现在我们在 Excel 中的数据如下所示:

        它们都是数字,我们可以在进一步的计算中使用它们。

        完整代码

        from pandas import DataFrame, MultiIndex, IndexSlice, concat
        from numpy.random import default_rng
        
        # Initial parameters
        rng = default_rng(0)
        data_length = 100
        genres = ['Pop', 'Dance', 'Rock', 'Jazz']
        values = [1, 2, 3, 4, 5]
        formula = ['counts', 'percent']
        file_name = 'test.xlsx'
        
        # Prepare data
        data = rng.integers(min(values), max(values), size=(data_length, len(genres)), endpoint=True)
        df = DataFrame(data, columns=genres)
        
        # Prepare a container for counted data 
        index = MultiIndex.from_product([formula, values], names=['formula', 'values'])
        counted = DataFrame(index=index)
        
        # Fill in counted data
        for col in df.columns:
            counts = df[col].value_counts()
            percent = counts / counts.sum()
            counted[col] = concat([counts, percent], keys=formula)
        
        # Apply number formatting and save the data in a Excel file
        styled_data = (
            counted.style
            .set_properties(**{'number-format': '0'}, subset=IndexSlice['counts', :])
            .set_properties(**{'number-format': '0%'}, subset=IndexSlice['percent', :])
        )
        styled_data.to_excel(file_name)
        

        附言

        注意不要混淆。对于使用的虚拟数据,我们可以在countspercent 部分中看到相同的值。那是因为数据是如何构建的。我用了100 个值的总数在初始数据帧df。所以value_counts 的数量和它们的百分比是相等的。


        蟒蛇 3.11.0
        熊猫 1.5.1
        numpy 1.23.4

        更新

        如果我们想保留原始数据每一列的值,但使用Styler 为输出帧的后半部分设置数字格式,那么我们应该以某种方式重命名Index 列,因为Styler 需要唯一列/传递的DataFrame 中的索引标签。我们可以将它们重命名为“Values.Pop”、“Valuse.Dance”等。或者我们可以对列使用多索引,IMO 看起来更好:

        import pandas as pd
        from numpy.random import default_rng
        
        rng = default_rng(0)
        columns = ['Pop', 'Dance', 'Rock', 'Jazz']
        data = rng.integers(1, 5, size=(100, len(columns)), endpoint=True)
        
        df = pd.DataFrame(data, columns=columns)
        
        li = []
        
        for col in df.columns:
            value_counts = df[col].value_counts()
            value_percentage = value_counts / value_counts.sum()
            item = (
                pd.concat([value_counts, value_percentage])
                .rename('count')
                .rename_axis('value')
                .to_frame()
                .reset_index()
            )
            li.append(item)
        
        resultdf = pd.concat(li, axis=1, keys=df.columns)
        
        styled_result = (
            resultdf.style
            .set_properties(
                **{'number-format': '0%'}, 
                subset=pd.IndexSlice[len(resultdf)/2:, pd.IndexSlice[:,'count']])
        )
        styled_result.to_excel('my_new_excel.xlsx')
        

        在这种情况下,输出将如下所示:

      【讨论】:

      • 请帮忙
      • 我真正需要的是:li = [] for col in df.columns: value_counts = df[col].value_counts() value_percentage = df[col].value_counts(normalize=True).map('{:.0% }'.format) li.append(pd.concat([value_counts, value_percentage]).to_frame().reset_index()) resultdf = pd.concat(li, axis=1) resultdf.to_excel("resultdf.xlsx")但是请使用样式数据格式的帮助
      猜你喜欢
      • 2021-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-28
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      相关资源
      最近更新 更多