Как сгруппировать датафрейм и суммировать по подгруппам последовательных чисел в Python? - PullRequest
0 голосов
/ 21 ноября 2018

У меня есть фрейм данных со столбцом, содержащим идентификаторы, и другой столбец, содержащий цифры:

df1 = {'ID':[400, 400, 400, 400, 400, 400, 500, 500, 500, 500], 
      'Number':[1, 2, 3, 4, 8, 9, 22, 23, 26, 27]}

Вы можете заметить, что у каждого идентификатора есть соответствующие серии последовательных чисел в столбце «Число».Например:

Id 400 содержит серию длиной 4 {1, 2, 3, 4} и другую серию длиной 2 {8, 9}

Я хотел бы получить для каждогоId, средняя длина их соответствующих серий.В этом примере:

df2 = {'ID':[400, 500], 'avg_length':[3, 2]}

Любые идеи будут высоко оценены!

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

groupby + cumsum + value_counts

Вы можете использовать groupby с пользовательской функцией:

df = pd.DataFrame({'ID':[400, 400, 400, 400, 400, 400, 500, 500, 500, 500], 
                   'Number':[1, 2, 3, 4, 8, 9, 22, 23, 26, 27]})

def mean_count(x):
    return (x - x.shift()).ne(1).cumsum().value_counts().mean()

res = df.groupby('ID')['Number'].apply(mean_count).reset_index()

print(res)

    ID  Number
0  400     3.0
1  500     2.0
0 голосов
/ 21 ноября 2018

Это один из способов, дважды используется groupby,

df1['tmp'] = (df1.Number - df1.Number.shift() > 1).cumsum()

df1.groupby(['ID', 'tmp']).Number.count().groupby(level = 0).mean().reset_index(name = 'avg_length')

2.29 ms ± 75.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

    ID  avg_length
0   400 3
1   500 2

Опция 2: без применения дважды, все еще использует столбец tmp, созданный ранее

df1.groupby('ID').tmp.apply(lambda x: x.value_counts().mean()).reset_index(name = 'avg_length')

2.25 ms ± 99.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
...