Как разделить фрейм данных на основе последовательного индекса? - PullRequest
4 голосов
/ 22 мая 2019

У меня есть фрейм данных 'работа' с непоследовательным индексом, вот пример:

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

мне нужно извлечь из этого фрейма данных новые фреймы данных, содержащие только строки, в которых индекс является последовательным, поэтому в этом случаемоя цель состоит в том, чтобы

DF_1.index=[4464,4465,4466]
DF_2.index=[5123,5124]
DF_3.index=[5323]

поддерживал все столбцы.

Кто-нибудь может мне помочь?Спасибо!

Ответы [ 4 ]

6 голосов
/ 22 мая 2019

groupby

Вы можете создать идеально "последовательный" массив с

np.arange(10)

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Если бы я вычел это из индекса, который монотонно увеличивается, только те элементы индекса, которые были "последовательными", были бы равны. Это умный способ установить ключ для группировки по.

list_of_df = [d for _, d in df.groupby(df.index - np.arange(len(df)))]

И распечатайте каждый, чтобы доказать это

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

np.split

Вы можете использовать np.flatnonzero, чтобы определить, где различия не равны 1, и избегать использования cumsum и groupby

list_of_df = np.split(df, np.flatnonzero(np.diff(df.index) != 1) + 1)

Proof

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
4 голосов
/ 22 мая 2019

Вот альтернатива:

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

Мы используем тот факт, что непрерывная разность 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

Еще один способ увидеть, что мы ищем непоследовательность для группировки, может быть более читабельным:

non_sequence = pd.Series(df.index).diff() != 1
grouper = non_sequence.cumsum().values
dfs = [dfx for _ , dfx in df.groupby(grouper)]
0 голосов
/ 22 мая 2019

Вы можете использовать exec для создания нескольких фреймов данных и получения ожидаемых результатов:

df = pd.DataFrame({'Column1' : [10.5,11.3,10.3,11.3,10.6,18.6], 'Column2' : [10.5,11.3,10.3,11.3,10.6,18.6]})
df.index = [4464, 4465, 4466, 5123, 5124, 5323]

prev_index = df.index[0]
df_1 = pd.DataFrame(df.iloc[0]).T
num_df = 1
for i in df.index[1:]:
    if i == prev_index+1:
        exec('df_{} = df_{}.append(df.loc[{}])'.format(num_df, num_df, i))
    else :
        num_df += 1
        exec('df_{} = pd.DataFrame(df.loc[{}]).T'.format(num_df, i))
    prev_index = i
0 голосов
/ 22 мая 2019

Может быть, есть более элегантный способ записать это, но вот что работает для меня:

previous_index = df.index[0]
groups = {}
for x in df.index:
    if (x-previous_index) ==1 : 
        groups[max(groups.keys())].append(x)
    else:
        groups[len(groups.keys())]=[x]
    previous_index = x

output_dfs = []
for key, val in groups.items():
    print(key, val)
    output_dfs.append(df[df.index.isin(val)])

Ваши кадры данных будут храниться в output_dfs

output_dfs[0].index

[4464,4465,4466]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...