Панды: создать столбец от 1 до длины каждой группы - PullRequest
0 голосов
/ 01 июня 2018

У меня есть df, в котором есть группы.Для каждой группы я хотел бы сформировать новый столбец, который содержит целые числа от 1 до количества строк в этой группе.Следующая попытка не работает, так как создает одну строку с несколькими столбцами вместо одного столбца с несколькими строками.Почему это происходит?

df = pd.DataFrame(data = {"a": np.arange(5), "b": np.arange(5)[::-1], "id": [1,1,1,2,2]}).set_index("id")
df["c"] = df.groupby("id").apply(lambda x: np.arange(1, len(x)+1))

В качестве альтернативы, если я пытаюсь вернуть объект Series как в:

df["c"] = df.groupby("id").apply(lambda x: pd.Series(data = np.arange(1, len(x)+1)))

Это вызывает исключение, говоря, что индексы несовместимы (что имеет смыслпоскольку у возвращенного Series теперь есть MultiIndex)

Обновление : позвольте мне сделать этот вопрос немного более общим: как можно сделать groupby на кадре данных, возвращающем Series с тем же индексом, что и в кадре данных, чтобы результирующий ряд можно было объединить в исходный кадр данных?

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

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

df["c"] = df.groupby("id")["a"].transform(lambda x: np.arange(1, len(x)+1))
0 голосов
/ 01 июня 2018
df["c"] = 1 + df.groupby("id").cumcount()

Причина, по которой ваши решения не работают, заключается в том, что groupby & agg пытается создать результат для каждой группы , а не для каждой строки .Таким образом, следующее создает список чисел для каждой группы

df.groupby("id").apply(lambda x: np.arange(1, len(x)+1))

К вашему комментарию: Чтобы иметь the numbers in reverse, вы можете сделать groupby - sort - cumcount.

Для более общей необходимости вы можете проверить rolling / resample функции.


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

Вам нужно groupby + transform. Но это не будет работать для случаев кумулятивной работы, подобных этой. На самом деле это возможно, как показано в @Alex answer

df["c"] = df.groupby("id")["a"].transform(lambda x: np.arange(1, len(x)+1))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...