Панды: удаление и подсчет последовательных дубликатов с условием - PullRequest
2 голосов
/ 15 октября 2019

Я хочу отбросить и сосчитать дубликаты в столбце val , когда val равно 1 .

Затем установить start - первая строка и end - последняя строка последовательных дубликатов.

df = pd.DataFrame()
df['start'] = [1, 2, 3, 4, 5, 6, 18, 30, 31] 
df['end'] = [2, 3, 4, 5, 6, 18, 30, 31, 32]
df['val'] = [1 , 1, 1, 1, 1, 12, 12, 1, 1]

df

   start  end  val
0      1    2    1
1      2    3    1
2      3    4    1
3      4    5    1
4      5    6    1
5      6   18   12
6     18   30   12
7     30   31    1
8     31   32    1

Ожидаемый результат

   start  end  val
0      1    6    5
1      6   18   12
2     18   30   12
3     30   32    2

Я пытался. df[~((df.val==1) & (df.val == df.val.shift(1)) & (df.val == df.val.shift(-1)))]

  start  end  val
0      1    2    1
4      5    6    1
5      6   18   12
6     18   30   12
7     30   31    1
8     31   32    1

но я не могу понять, как завершить мой ожидаемый результат, любое предложение?

Ответы [ 3 ]

3 голосов
/ 15 октября 2019

Использование:

#mask by condition
m = df.val==1
#consecutive groups
g = m.ne(m.shift()).cumsum()
#filter by condition and aggregate per groups
df1 = df.groupby(g[m]).agg({'start':'first', 'end':'last', 'val':'sum'})
#concat together, for correct order create index by g
df = pd.concat([df1, df.set_index(g)[~m.values]]).sort_index().reset_index(drop=True)
print (df)
   start  end  val
0      1    6    5
1      6   18   12
2     18   30   12
3     30   32    2
2 голосов
/ 15 октября 2019

Вы также можете сделать двухслойную маску для группировки:

m = (df.val.ne(1) | df.val.ne(df.val.shift())).cumsum()
df = df.groupby(m).agg({'start': 'first', 'end': 'last', 'val': 'last'})
0 голосов
/ 15 октября 2019

Решение от @jezrael идеально, но здесь немного другой подход:

df['aux'] = (df['val'] != df['val'].shift()).cumsum()
df.loc[df['val'] == 1, 'end'] = df[df['val'] == 1].groupby('aux')['end'].transform('last')
df.loc[df['val'] == 1, 'val'] = df.groupby('aux')['val'].transform('sum')
df = df.drop_duplicates(subset=df.columns.difference(['start']), keep='first')
df = df.drop(columns=['aux'])

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