Агрегирование строковых данных из нескольких последовательных строк столбца на основе условий другого столбца - PullRequest
1 голос
/ 15 мая 2019

У меня есть такой DataFrame:

data = {'col1': ['A', 'B', 'B', 'A', 'B', 'C', 'B', 'B', 'B', 
                  'A', 'C', 'A', 'B', 'C'],
        'col2': ['NaN', 'comment1', 'comment2', 'NaN', 'comment3', NaN,
                 'comment4', 'comment5', 'comment6', 
                 'NaN', 'NaN', 'NaN', 'comment7', 'NaN]}

frame = pd.DataFrame(data)
frame

col1  col2
A     NaN
B     comment1
B     comment2
A     NaN
B     comment3
C     NaN
B     comment4
B     comment5
B     comment6
A     NaN
C     NaN
A     NaN
B     comment7
C     NaN

В каждой строке с col1 == 'B' есть комментарий, который будет строкой.Мне нужно объединить комментарии и заполнить предыдущую строку (где col1! = 'B') результирующей агрегированной строкой.

Любая строка, в которой col1! = 'B' может не иметь ни одного, одного или нескольких соответствующихстроки комментариев (col1 == 'B'), которые, кажется, суть проблемы.Я не могу просто использовать fillna ('bfill') и т. Д.

Я изучил циклы iterrows (), groupby (), while и попытался построить свою собственную функцию.Но я не думаю, что полностью понимаю, как все это работает.

Готовый продукт должен выглядеть следующим образом:

col1    col2
A       comment1 + comment2
B       comment1
B       comment2
A       comment3
B       comment3
C       comment4 + comment5 + comment6
B       comment4
B       comment5
B       comment6
A       NaN
C       NaN
A       comment7
B       comment7
C       NaN

В конце концов я буду отбрасывать все строки, где col1== 'B', но сейчас я бы хотел оставить их для проверки.

Ответы [ 2 ]

3 голосов
/ 15 мая 2019

Вот один из способов использования GroupBy с пользовательским группировщиком для объединения строк, где col1 равно B:

where_a = frame.col1.ne('B') 
g = where_a.cumsum()
com = frame[frame.col1.eq('B')].groupby(g).col2.agg(lambda x: x.str.cat(sep=' + '))
till = (frame.col2.isna() & frame.col2.shift(-1).notna())[::-1].idxmax()
ixs = where_a[:till+1].reindex(frame.index).fillna(False)
frame.loc[ixs, 'col2'] = com.values

print(frame)

    col1                         col2
0     A             comment1 + comment2
1     B                        comment1
2     B                        comment2
3     A                        comment3
4     B                        comment3
5     C  comment4 + comment5 + comment6
6     B                        comment4
7     B                        comment5
8     B                        comment6
9     A                             NaN
10    C                             NaN
0 голосов
/ 22 мая 2019
df['col_group'] = -1
col_group = 0
for i in df.index:
    if df.loc[i, 'col1'] != 'B':
        col_group += 1
    df.loc[i, 'col_group'] = col_group

comments = df[df['col1'] == 'B']
transactions = df[df['col1'] != 'B']
agg_comments = comments.groupby('col_group')['col2'].apply(lambda x: reduce(lambda i,j: i+"&$#"+j,x)).reset_index()
df = pd.merge(transactions, agg_comments, on='col_group', how='outer')
...