【问题标题】:How to drop row index and flatten index in this way如何以这种方式删除行索引和展平索引
【发布时间】:2021-01-31 08:41:13
【问题描述】:

我有以下dfe :-

id       categ  level  cols           value   comment
1         A      PG    Apple           428    comment1 
1         A      CD    Apple           175    comment1 
1         C      PG    Apple           226    comment1 
1         C      AB    Apple           884    comment1 
1         C      CD    Apple           288    comment1 
1         B      PG    Apple           712    comment1 
1         B      AB    Apple           849    comment1 
2         B      CD    Apple           376    comment1 
2         C      None  Orange          591    comment1 
2         B      CD    Orange          135    comment1 
2         D      None  Orange          423    comment1 
2         A      AB    Orange          1e13   comment1 
2         D      PG    Orange          1e15   comment2 





   df2 = pd.DataFrame({'s2': {0: 1, 1: 2, 2: 3}, `level': {0: 'PG', 1: 'AB', 2: 'CD'}})
    df1 = pd.DataFrame({'sl': {0: 1, 1: 2, 2: 3, 3: 4}, 'set': {0: 'A', 1: 'C', 2: 'B', 3: 'D'}})
    dfe = (dfe[['categ','level','cols','id','comment','value']]
            .merge(df1.rename({'set' : 'categ'}, axis=1),how='left',on='categ')
            .merge(df2, how='left', on='level'))
    na = dfe['level'].isna()
    
    dfs = {'no_null': dfe[~na], 'null': dfe[na]}
    
    with pd.ExcelWriter('XYZ.xlsx') as writer: 
        
        for p,r in dfs.items():
            if p== 'no_null':
    
                c= ['cols','s2','level']
            else:
    
                 c = 'cols'
            
            df = r.pivot_table(index=['id','sl','comment','categ'], columns=c, values=['value'])
            df.columns = df.columns.droplevel([0,2])
            df  = df.reset_index().drop(('sl',''), axis=1).set_index('categ')
            
            
            for (id,comment), sdf in df.groupby(['id','comment']):
                df = sdf.reset_index(level=[1], drop=True).dropna(how='all', axis=1)
                df.to_excel(writer,sheet_name=name)

运行它,我会以这种方式在 excel 中显示结果:-

我想以某种方式订购,我试过了:-

df = r.pivot_table(index=['id','sl','comment','categ'], columns=c, values='value')
            df.columns = df.columns.droplevel([1])
            df  = df.reset_index().drop(('sl',''), axis=1).set_index('categ')

这给了我Too many levels: Index has only 2 levels, not 3 错误,我不知道我在这里错过了什么/错了。

我对标题排列的预期输出是:-

想知道标题是否可以写成大写字母的 excel,如预期输出所示。

编辑 1 我尝试了答案,我得到了这个观点:-

我希望能够只显示一次 IDCOMMENT(因为它已经在代码逻辑中按 ID 分组),然后删除 sl 列和第一列 0,1,2 并删除0上方的空白行

【问题讨论】:

  • 问题出在这里:df.columns = df.columns.droplevel([0,2])你的栏目没有三层:[0,1,2]
  • 我几乎尝试了所有方法,但我无法解决问题..mtried 将列名 sa 赋予droplevel
  • 列是什么样的?将df.columns = df.columns.droplevel([0,2]) 替换为print(df.columns) 并将打印功能的结果添加到您的问题中。
  • 我无法运行它,因为它给出了错误,我已经展示了它的样子,而在我的问题中没有删除 sl..
  • @scott Boston 我的目标是让标题按照我在预期输出中提供的方式对齐,我无法得到它,尝试了各种扁平化方式..

标签: pandas dataframe pivot-table


【解决方案1】:

给定 dfe 为:

   categ level    cols  id   comment         value  sl   s2
0      A    PG   Apple   1  comment1  4.280000e+02   1  1.0
1      A    CD   Apple   1  comment1  1.750000e+02   1  3.0
2      C    PG   Apple   1  comment1  2.260000e+02   2  1.0
3      C    AB   Apple   1  comment1  8.840000e+02   2  2.0
4      C    CD   Apple   1  comment1  2.880000e+02   2  3.0
5      B    PG   Apple   1  comment1  7.120000e+02   3  1.0
6      B    AB   Apple   1  comment1  8.490000e+02   3  2.0
7      B    CD   Apple   2  comment1  3.760000e+02   3  3.0
8      C  None  Orange   2  comment1  5.910000e+02   2  NaN
9      B    CD  Orange   2  comment1  1.350000e+02   3  3.0
10     D  None  Orange   2  comment1  4.230000e+02   4  NaN
11     A    AB  Orange   2  comment1  1.000000e+13   1  2.0
12     D    PG  Orange   2  comment2  1.000000e+15   4  1.0

那就试试吧:

df = dfe.pivot_table(index=['id','comment','categ'], columns=c, values='value')
df.columns = df.columns.droplevel([1])

df = (df.rename_axis(columns=[None, None])
        .reset_index(col_level=1)
        .rename(columns = lambda x: x.upper()))
df.to_excel('testa1.xlsx')

输出:

注意事项:

  • 删除了 pivot_table 中“值”周围的 [],以不包含“值”作为 列索引。
  • 使用col_level 参数将“categ”、“label”和“cmets”与列索引级别 1 对齐。
  • 请参阅这篇关于空白行的帖子,https://stackoverflow.com/a/52498899/6361531

【讨论】:

  • 感谢您的回答,我试试看..有没有办法让IDCOMMENTCATEGAPPLEORANGE一致跨度>
  • 好的,去掉 'col_level=1' 参数。
  • 在我编写 for (id,comment), sdf in df.groupby(['id','comment']): df = sdf.reset_index(level=[1], drop=True).dropna(how='all', axis=1) 的代码中,我将 df = (df.rename_axis(columns=[None, None]) .reset_index(col_level=1) .rename(columns = lambda x: x.upper())) 放在了这个块之后,它给了我 ValueError: Length of names must match number of levels in MultiIndex.。我不明白这条线到底放在哪里,因为我已经循环了dfs
  • 我仍然怀疑您的 dfs 中的条目之一有问题。在第一次迭代 fo dfs 上运行 for。如果 dfs 中有 null 或空数据框,则需要在 forloop 中添加一些跳过逻辑。
  • 你现在能看看我的编辑吗..我希望能够只打印一次 IDCOMMENT(就像我之前能够显示的那样)并删除空白行和 @ 987654339@ 列和第一列.. 不知怎的我做不到..
【解决方案2】:

我认为删除列名称并将其替换为自定义名称会更容易:

df.columns = df.columns.droplevel()
df.columns = pd.MultiIndex.from_tuples([("", "ID"), ("", "CATEG"), ("apple", "PG"), ("apple", "AB"), ("apple", "CD"), ("orange", "PG"), ("orange", "AB"), ("orange", "CD")])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-19
    • 2022-07-20
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多