在 pandas 组之间添加多个空行而不附加

Adding more than one empty row between pandas groups without append

提问人:TStein 提问时间:11/15/2023 更新时间:11/15/2023 访问量:58

问:

我想在我的 pandas 数据帧中的每个 groupby 之间添加几个空行。我知道过去曾问过类似的问题,但我能找到的所有答案都依赖于最近停止的追加功能。我想我离得很近,但我无法让它工作。

从我所读到的内容来看,这个想法是让 concat 函数替换 append,所以我一直在尝试 1) 创建我的组,2) 使用正确的列和行数制作一个空白数据帧,然后 3) 遍历组并将它们单独与空白数据帧连接起来。这看起来像这样:

当前 df:

    column1    column2    column3
0      a          1        blue
1      b          2        blue
2      a          1        green
3      b          2        green
4      a          1        black
5      b          2        black

注意:我的 df 已经按 column3 排序,因此它们已经以这种方式“分组”

我正在尝试:

# Create my groups by the desired column
dfg = df.groupby("column3")

# Create my blank df with the same columns as my main df and with the desired number of blank rows
blank_df5 = pd.DataFrame(columns=['column1','column2','column3'],index=['0','1','2','3','4'])

# Loop through and concatenate groups and the blank df
for colors in dfg:
    pd.concat([colors, blank_df5], ignore_index=True)

print(dfg)

这返回了:TypeError:无法连接类型为“<类'元组'>”的对象;只有 Series 和 DataFrame 对象有效

我所期望/想要的:

    column1    column2    column3
0      a          1        blue
1      b          2        blue
0
1
2
3
4
2      a          1        green
3      b          2        green
0
1
2
3
4
4      a          1        black
5      b          2        black

然后,我尝试将这些组变成他们自己的dfs,然后循环访问:

dfg = df.groupby('column1')
[dfg.get_group(x) for x in dfg.groups]

blank_df5 = pd.DataFrame(columns=['column1','column2','column3'],index=['0','1','2','3','4'])

for colors in dfg:
    pd.concat([colors, blank_df5], ignore_index=True)

# I also tried [pd.concat([colors, blank_df5], ignore_index=True) for column3 in dfw] with the same result

结果仍然是:TypeError:无法连接类型为“<类'元组'>”的对象;只有 Series 和 DataFrame 对象有效

我尝试过的其他方法:

mask = df['column3'].ne(df['column3'].shift(-1))
df1 = pd.DataFrame('', index=mask.index[mask] + .5, columns=df.columns)

dfg = pd.concat([df,df1]).sort_index().reset_index(drop=True).iloc[:-1]

print(dfg)

这可以在组之间添加一个空行,但我无法让它添加更多。

dfg = (pd.concat([df, 
            df.groupby('column3').apply(lambda x: x.shift(-1).iloc[-1]).reset_index()])
           .sort_values('column3')
           .reset_index(drop=True))

print(dfg)

这将返回:ValueError: cannot insert column3, already exists

dfg = df.groupby('column1')

for colors in dfg:
        new_rows = 5
        new_index = pd.RangeIndex(len(colors)*(new_rows+1))
        dfg = pd.DataFrame(np.nan, index=new_index, columns=df.columns)
        ids = np.arange(len(colors))*(new_rows+1)
        dfg.loc[ids] = df.values

print(dfg)

这将返回:ValueError:无法将输入数组从形状 (710,) 广播到形状 (2,) 如果我删除循环并只运行循环中的内容,它会在每行数据之间添加空行。

希望这是有道理的,提前感谢您的任何帮助。

如果有人好奇,我需要这样做的原因是以这种格式将其转储到 excel 中(我知道,这是公司的决定,而不是我的决定),以便进一步的人工分析和操作。我正在使用 xlwings 进行转储,但我找不到在转储期间或之后用 xlwings 拆分它的方法。不过,我绝对愿意接受有关如何做到这一点的建议。

Python Pandas Group-由 xlwings

评论

0赞 SiP 11/15/2023
遍历组时,组名称和组本身 (df) 位于元组中。向 for 循环添加一个变量:for a, b in df.groupby...
0赞 TStein 11/15/2023
对不起,我可能只是很密集,但在我的例子中,变量中的“颜色”不是吗?for colors in dfg:
0赞 SiP 11/15/2023
不,请注意逗号和 之间的 2 个变量。你不密集。这是一个正常的问题for color_name, colors in dfgforin

答:

0赞 Suraj Shourie 11/15/2023 #1

您可以尝试在每种颜色之后附加空白行,但附加是一个低效的问题。

看看这里这里的答案,我发现下面的代码是一个更好的解决方案。请注意,我假设颜色组始终以 2 个为一组,如果不是这样,则必须更改代码。

import numpy as np
# create an empty dataframe with the required numbers of rows first
n = 3 # num of blank rows to add
new_index = pd.RangeIndex(len(df)/2*(n+1))
new_df = pd.DataFrame(np.nan, index=new_index, columns=df.columns)

# fill it with original data frame values at the required indices:

arr = np.arange(0,len(new_df), step=n+2),np.arange(1,len(new_df), step=n+2)
ids = np.sort(np.concatenate(arr))
new_df.loc[ids] = df.values
new_df

输出:

   column1  column2 column3
0        a      1.0    blue
1        b      2.0    blue
2      NaN      NaN     NaN
3      NaN      NaN     NaN
4      NaN      NaN     NaN
5        a      1.0   green
6        b      2.0   green
7      NaN      NaN     NaN
8      NaN      NaN     NaN
9      NaN      NaN     NaN
10       a      1.0   black
11       b      2.0   black

评论

0赞 TStein 11/15/2023
对不起,我应该在我的例子中澄清。我的组都有未知且不一致的行数。我想不出一种方法在您的代码中解释这一点。不过你是对的,如果它们包含一致的数据量,这将很好地工作。
1赞 Timeless 11/15/2023 #2

遵循您的第二种方法:

N = 5

grps = df.groupby("column3", sort=False)

out = pd.concat(
    [
        pd.concat([g, pd.DataFrame("", index=range(N), columns=df.columns)])
        if i < len(grps)-1 else g for i, (_, g) in enumerate(grps)
    ]
)

输出:

print(out)

  column1 column2 column3
0       a       1    blue
1       b       2    blue
0                        
1                        
2                        
3                        
4                        
2       a       1   green
3       b       2   green
0                        
1                        
2                        
3                        
4                        
4       a       1   black
5       b       2   black

[16 rows x 3 columns]