2016-11-07 4 views
1

У меня есть очень большой DF, который содержит данные, такие как следующие:Переменный размер Chunk Панды Dataframe

import pandas as pd 
df = pd.DataFrame() 
df['CODE'] = [1,2,3,1,2,4,2,2,4,5] 
df["DATA"] = [ 'AA', 'BB', 'CC', 'DD', 'AA', 'BB', 'EE', 'FF','GG', 'HH'] 
df.sort_values('CODE') 
df 
    CODE DATA 
0  1 AA 
3  1 DD 
1  2 BB 
4  2 AA 
6  2 EE 
7  2 FF 
2  3 CC 
5  4 BB 
8  4 GG 
9  5 HH 

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

В принципе, если я выбрать размер куска 4 строк, первая порция может быть увеличена до включать все элементы с «2» и быть:

chunk1: 
     CODE DATA 
0  1 AA 
3  1 DD 
1  2 BB 
4  2 AA 
6  2 EE 
7  2 FF 

Я нашел некоторые сообщения о комков и группировки, как следующее :

split dataframe into multiple dataframes based on number of rows

Однако выше, обеспечивают одинаковый размер комков и мне нужен умный отрывов, который учитывает значения в столбце кода.

Любые идеи, как это сделать?

ответ

0

Возможно, я придумал решение (все еще проверяя al l случаев), но не очень элегантный.

создать рекурсивную функцию, возвращающую интервалы принять:

def findrange(start,step): 
     for i in range(start,len(df)+1, step): 
      if i+step > len(df): return [i, len(df)] 
      if df.CODE[i+step:i+step+1].values != df.CODE[i+step-1:i+step].values: 
       return [i,i+step] 
     else: 
      return findrange(i,step+1) 

Тогда я вызываю функцию, чтобы получить диапазоны и обрабатывать данные

interval = [0,0] 
idx = 0 
N=2 
while interval[1] < len(df): 
    if idx < interval[1]: idx = interval[1] 
    interval = findrange(idx, N) 
    idx+=N # this point became useless once interval[1] > idx 

я пытался с DF отправил используя многие различные значения для N> 0 и выглядят хорошо. если у вас есть подход, то больше панд, как я открыт для этого.

0

Я думаю, что вы можете создать новый столбец GROUPS по cumcount, а затем пол разделить на N - получить куски для каждого CODE значений:

N = 2 
df['GROUPS'] = df.groupby('CODE').cumcount() // N 
print (df) 
    CODE DATA GROUPS 
0  1 AA  0 
3  1 DD  0 
1  2 BB  0 
4  2 AA  0 
6  2 EE  1 
7  2 FF  1 
2  3 CC  0 
5  4 BB  0 
8  4 GG  0 
9  5 HH  0 

groups = df.groupby(['CODE','GROUPS']) 
for (frameno, frame) in groups: 
    print (frame.to_csv("%s.csv" % frameno)) 

Вы также можете создать новую Series и использовать его для groupby:

chunked_ser = df.groupby('CODE').cumcount() // N 
print (chunked_ser) 
0 0 
3 0 
1 0 
4 0 
6 1 
7 1 
2 0 
5 0 
8 0 
9 0 
dtype: int64 

groups = df.groupby([df.CODE,chunked_ser]) 
for (frameno, frame) in groups: 
    print (frame.to_csv("%s.csv" % frameno)) 
+0

но с N = 2, например, я заканчиваю разделение строк, имеющих CODE равным 2. Вместо этого я бы сохранил их в одном куске. – user2320577

+0

Хммм, я понимаю, что вам нужно разделить каждую группу по столбцу «Код» на большее количество групп, потому что большие данные. Таким образом, вы можете использовать большие 'N', такие как 1000, а затем разделять на 1000 рядов строк. Или я что-то не хватает? – jezrael

+0

Если используется разделение пола, например, попробуйте 'N = 3' получить последнюю группу с размером' 1' - получить ту же самую длину для большинства групп, но последнее может быть обрезано меньше. – jezrael

Смежные вопросы