Столбец агрегированного (объединенного) текста на основе условий в pandas - PullRequest
2 голосов
/ 19 июня 2020

У меня есть следующий набор данных:

task = ['duty of care','informed consent','records management','conducting','experiments','positive reinforcement','developing','rapport' ]
start = [ 21, 24, 26,  60, 61, 80,98,99 ]
end = [ 24, 26, 28,  61,  62, 82,99,100]

dat = pd.DataFrame({'task': task, 'start':start, 'end': end})
dat

enter image description here

То, что я хочу выполнить sh, это

  1. если dat.end[i] == dat.start[i+1], то агрегировать dat.task
  2. если dat.end[i] != dat.start[i+1] ничего не делать

Желаемый результат должен выглядеть так.

enter image description here

Ответы [ 2 ]

4 голосов
/ 19 июня 2020

Нам понадобится способ сгруппировать их вместе, если они являются частью блока. Во-первых, давайте найдем все моменты, когда начало не совпадает с концом следующего элемента. Эта серия имеет значение True, если элемент является первым в блоке, и false в противном случае.

temp = (dat['start'] != dat['end'].shift(1))

Это выглядит так:

0     True
1    False
2    False
3     True
4    False
5     True
6     True
7    False

Затем мы можем взять кумулятивную сумму. Когда вы сделаете это для True / False, True добавит 1 к сумме, а False не изменит ее. Это полезно, потому что тогда мы получаем группировку - каждый блок, который вы хотели объединить, изначально имеет свой собственный номер, связанный с ним.

groups = temp.cumsum()

выглядит так:

0    1
1    1
2    1
3    2
4    2
5    3
6    4
7    4

Теперь мы почти у цели. Для каждой группы вы хотите получить минимальное начало, максимальное значение и объединить весь текст.

datg = dat.groupby(groups)
out = pd.DataFrame({
    'task':  datg['task'].apply(' '.join),
    'start': datg['start'].min(),
    'end':   datg['end'].max(),
})

Это дает окончательный результат: в одном месте:

temp = (dat['start'] != dat['end'].shift(1))
groups = temp.cumsum()
datg = dat.groupby(groups)
out = pd.DataFrame({
    'task':  datg['task'].apply(' '.join),
    'start': datg['start'].min(),
    'end':   datg['end'].max(),
    })
1 голос
/ 19 июня 2020

IIU C вы можете сначала создать новый столбец, используя cumsum и groupby этот столбец:

df = pd.DataFrame({'task': task, 'start':start, 'end': end})

df["count"] = (df["start"]-df["end"].shift(1)).fillna(0).ne(0).cumsum()
print (df.groupby("count").agg({"task":"first","start":"min","end":"max"}))

                         task  start  end
count                                    
0                duty of care     21   28
1                  conducting     60   62
2      positive reinforcement     80   82
3                  developing     98  100
...