С точки зрения наименьшей вычислительной сложности, как создать новый столбец pandas, который увеличивается на определенное число на основе другого столбца

#python #pandas

#python #pandas

Вопрос:

У меня есть этот столбец чисел, отсортированных по значению

 import pandas as pd 
  
# initialize list of lists 
data = [1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 5, 6, 6, 6]
  
# Create the pandas DataFrame 
df = pd.DataFrame(data, columns = ['First']) 
df.head(19)

First
0   1
1   1
2   1
3   1
4   2
5   2
6   3
7   3
8   3
9   3
10  3
11  3
12  4
13  4
14  5
15  6
16  6
17  6

 

Я хотел бы добавить столбец, который увеличивается на определенное число вниз по столбцу, если значение столбца в определенной строке совпадает с предыдущим значением. При переходе по строкам и обнаружении нового значения строки в ‘First’, приращения перезапускаются на 1 (или ноль).

Вот пример фрейма данных результата, который я ищу.

     First   Second
0   1   1
1   1   2
2   1   3
3   1   4
4   2   1
5   2   2
6   3   1
7   3   2
8   3   3
9   3   4
10  3   5
11  3   6
12  4   1
13  4   2
14  5   1
15  6   1
16  6   2
17  6   3
 

Что пробовали до сих пор

Я попытался извлечь столбец в список и использовать цикл для создания нового столбца, который затем можно добавить к dataframe

 colimnList = df['First'].tolist()
newColumn = []
old = -1
toAdd = 1 
for item in colimnList:
    if item == old:
        toAdd =1
        newColumn.append(toAdd)
    else:
        toAdd=1
        newColumn.append(toAdd)
        old = item
newColumn

[1, 2, 3, 4, 1, 2, 1, 2, 3, 4, 5, 6, 1, 2, 1, 1, 2, 3]
 

Есть ли метод, который является более эффективным в вычислительном отношении или, по крайней мере, более элегантным с программной точки зрения? Возможно, сделано в чистых пандах?

Ответ №1:

В Pandas есть операция «groupby», которая выполняет почти именно то, что вам нужно, называется cumcount . Он запускает каждую группу с нуля, тогда как вы хотите начать с единицы, поэтому просто добавьте единицу, и вы получите желаемый результат:

 df.groupby('First').cumcount()   1