Получить связные подмножества из серии панд - PullRequest
0 голосов
/ 14 марта 2019

Я довольно новичок в пандах и недавно столкнулся с проблемой.У меня есть DataFrame, который мне нужно обработать.Мне нужно извлечь части DataFrame, где выполняются определенные условия.Однако я хочу, чтобы эти части были связными блоками, а не одним большим набором.

Пример: Рассмотрим следующие панды DataFrame

   col1  col2
0      3     11
1      7     15
2      9     1
3     11     2
4     13     2
5     16     16
6     19     17
7     23     13
8     27     4
9     32     3

Я хочу извлечь подкадрыгде значения col2> = 10, в результате чего может быть в списке DataFrames в виде (в данном случае):

   col1  col2
0      3     11
1      7     15


   col1  col2
5     16     16
6     19     17
7     23     13

В конечном счете, мне нужно провести дополнительный анализ значений в col1 внутри полученных частей.Однако начало и конец каждого из этих блоков важны для меня, поэтому, думаю, простое создание подмножества с использованием pandas.DataFrame.loc не сработает.

То, что я пробовал: Прямо сейчас у меня есть обходной путь, который получает подмножество, используя pandas.DataFrame.loc, а затем извлекает начальный и конечный индексы каждого связного блока впоследствии, перебирая подмножествои проверьте, есть ли скачок в индексах.Тем не менее, это выглядит довольно неуклюже, и я чувствую, что мне здесь не хватает базовой функции панд, которая сделала бы мой код более эффективным и чистым.

Это код, представляющий мой текущий обходной путь, адаптированный к приведенному выше примеру.

# here the blocks will be collected for further computations
blocks = []

# get all the items where col2 >10 using 'loc[]'
subset = df.loc[df['col2']>10]

block_start = 0
block_end = None

#loop through all items in subset
for i in range(1, len(subset)):
    # if the difference between the current index and the last is greater than 1 ...
    if subset.index[i]-subset.index[i-1] > 1:
        # ... this is the current blocks end
        next_block_start = i
        # extract the according block and add it to the list of all blocks
        block = subset[block_start:next_block_start]
        blocks.append(block)
        #the next_block_start index is now the new block's starting index
        block_start = next_block_start
#close and add last block
blocks.append(subset[block_start:])

Редактировать : я по ошибке ранее ссылался на pandas.DataFrame.where 'вместо «pandas.DataFrame.loc».Я, кажется, немного смущен моими недавними исследованиями.

1 Ответ

1 голос
/ 14 марта 2019

Вы можете разбить свою проблему на части. Сначала вы проверяете условие:

df['mask'] = (df['col2']>10)

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

df['new'] = df['mask'].gt(df['mask'].shift(fill_value=False))

Теперь вы можете объединить эту информацию в номер группы. cumsum сгенерирует пошаговую функцию, которую мы установим на ноль (через столбец mask), если это не группа, которая нас интересует.

df['grp'] = (df.new + 0).cumsum() * df['mask']

EDIT

Вам не нужно делать групповые вычисления в вашем df:

s = (df['col2']>10)
s = (s.gt(s.shift(fill_value=False)) + 0).cumsum() * s

После этого вы можете разделить это на dict отдельных DataFrames

grp = {}
for i in np.unique(s)[1:]:
    grp[i] = df.loc[s == i, ['col1', 'col2']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...