如何基于连续索引拆分数据帧?

Fab*_*gio 5 python dataframe pandas

我有一个具有非连续索引的数据帧“工作”,这里是一个示例:

Index Column1 Column2
4464  10.5    12.7
4465  11.3    12.8
4466  10.3    22.8
5123  11.3    21.8
5124  10.6    22.4
5323  18.6    23.5
Run Code Online (Sandbox Code Playgroud)

我需要从此数据框中提取仅包含索引连续的行的新数据框,因此在这种情况下,我的目标是获取

DF_1.index=[4464,4465,4466]
DF_2.index=[5123,5124]
DF_3.index=[5323]
Run Code Online (Sandbox Code Playgroud)

维护所有列。

谁能帮我?谢谢!

piR*_*red 6

groupby

您可以使用以下方法制作完美的“连续”数组

np.arange(10)

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Run Code Online (Sandbox Code Playgroud)

如果我从单调增加的索引中减去此值,则只有那些“连续”的索引成员才会显示为相等。这是建立分组依据的聪明方法。

list_of_df = [d for _, d in df.groupby(df.index - np.arange(len(df)))]
Run Code Online (Sandbox Code Playgroud)

并打印每个证明

print(*list_of_df, sep='\n\n')

       Column1  Column2
Index                  
4464      10.5     12.7
4465      11.3     12.8
4466      10.3     22.8

       Column1  Column2
Index                  
5123      11.3     21.8
5124      10.6     22.4

       Column1  Column2
Index                  
5323      18.6     23.5
Run Code Online (Sandbox Code Playgroud)

np.split

您可以使用np.flatnonzero来确定差异不相等的地方,1并避免使用cumsumgroupby

list_of_df = np.split(df, np.flatnonzero(np.diff(df.index) != 1) + 1)
Run Code Online (Sandbox Code Playgroud)

证明

print(*list_of_df, sep='\n\n')

       Column1  Column2
Index                  
4464      10.5     12.7
4465      11.3     12.8
4466      10.3     22.8

       Column1  Column2
Index                  
5123      11.3     21.8
5124      10.6     22.4

       Column1  Column2
Index                  
5323      18.6     23.5
Run Code Online (Sandbox Code Playgroud)


Ant*_*vBR 5

这是一个替代方案:

grouper = (~(pd.Series(df.index).diff() == 1)).cumsum().values  
dfs = [dfx for _ , dfx in df.groupby(grouper)]
Run Code Online (Sandbox Code Playgroud)

我们使用一个事实,即连续的差值为1等于一个序列(diff == 1)。

完整示例:

import pandas as pd

data = '''\
Index Column1 Column2
4464  10.5    12.7
4465  11.3    12.8
4466  10.3    22.8
5123  11.3    21.8
5124  10.6    22.4
5323  18.6    23.5
'''

fileobj = pd.compat.StringIO(data)
df = pd.read_csv(fileobj, sep='\s+', index_col='Index')

non_sequence = pd.Series(df.index).diff() != 1
grouper = non_sequence.cumsum().values
dfs = [dfx for _ , dfx in df.groupby(grouper)]

print(dfs[0])

#       Column1  Column2
#Index                  
#4464      10.5     12.7
#4465      11.3     12.8
#4466      10.3     22.8
Run Code Online (Sandbox Code Playgroud)

另一种看待它的方式是,我们寻找groupby的非序列,可能更易读:

non_sequence = pd.Series(df.index).diff() != 1
grouper = non_sequence.cumsum().values
dfs = [dfx for _ , dfx in df.groupby(grouper)]
Run Code Online (Sandbox Code Playgroud)