Объединить строки Groupby / применить функцию

#python #dataframe #group-by #apply

#python #фрейм данных #группировать по #применить

Вопрос:

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

     ID  Group   Start   End
0   ID1   A       1      2
1   ID1   A       2      3
2   ID1   A       3      4
3   ID1   B       4      5
4   ID1   B       5      6
5   ID2   A       6      7
6   ID2   A       7      8
7   ID2   B       8      9
8   ID2   B       9     10
9   ID2   B       11    12
  

Я хочу создать новый фрейм данных, где, если для уникального идентификатора конечное значение равно начальному значению из другой строки, его следует объединить в одну строку (идентификаторы должны быть в одной группе).
Итак, я хочу, чтобы это было так (dataframe2):

     ID  Group   Start   End
0   ID1   A       1      4
3   ID1   B       4      6
5   ID2   A       6      8
7   ID2   B       8      10
9   ID2   B       11     12
  

Сейчас это слишком сложно для меня. Итак, в первую очередь я подумал о sth с groupby и apply. Я сдвинул конечный столбец на единицу (направление вниз) в каждой группе и проверил, сколько раз начальное значение равно значениям end_shifted (я также могу использовать это при последующем анализе набора данных, так что это не так уж и бесполезно). Итак, я написал функцию:

 def mygroup(df):
    
    is_continued = 0
    
    df['End'] = df['End'].shift(1)
    for index, row in df.iterrows():
        if (row['Start'] == row['End']):
            is_continued = is_continued   1
            
    return is_continued
  

и затем:

 is_continued = dataframe.groupby(['ID']).apply(mygroup)
  

Я думал, что это даст мне 4 для ID1 и 4 для ID2, но нет.

 ID
ID1    4
ID2    0
dtype: int64
  

Итак, мои вопросы.

  1. Что я делаю не так с groupby / apply.
  2. Как я могу объединить эти строки, чтобы получить dataframe2?

Ответ №1:

У меня очень мало опыта работы с Pandas, и поэтому (1) я не могу ответить на ваш первый вопрос и (2) что касается вашего второго вопроса, это, вероятно, не так, как это сделал бы эксперт. Но я предлагаю это как решение:

 import pandas as pd


def combine_rows(df):
    id = []
    group = []
    start = []
    end = []
    prev_row = None
    for index, row in df.iterrows():
        if prev_row is None:
            prev_row = row
            prev_end = prev_row.End
            continue
        if row.ID == prev_row.ID and row.Group == prev_row.Group and row.Start == prev_end:
            prev_end = row.End
        else:
            id.append(prev_row.ID)
            group.append(prev_row.Group)
            start.append(prev_row.Start)
            end.append(prev_end)
            prev_row = row
            prev_end = prev_row.End
    if prev_row is not None:
        id.append(prev_row.ID)
        group.append(prev_row.Group)
        start.append(prev_row.Start)
        end.append(prev_end)
    return pd.DataFrame({"ID": id, "Group": group, "Start": start, "End": end})

        
df = pd.DataFrame({
    "ID": ['ID1', 'ID1', 'ID1', 'ID1', 'ID1', 'ID2', 'ID2', 'ID2', 'ID2', 'ID2'],
    "Group": ['A', 'A', 'A', 'B', 'B', 'A', 'A', 'B', 'B', 'B'],
    "Start": [1, 2, 3, 4, 5, 6, 7, 8, 9, 11],
    "End": [2, 3, 4, 5, 6, 7, 8, 9, 10, 12]
})
print(df)
df = combine_rows(df)
print(df))
  

С принтами:

     ID Group  Start  End
0  ID1     A      1    2
1  ID1     A      2    3
2  ID1     A      3    4
3  ID1     B      4    5
4  ID1     B      5    6
5  ID2     A      6    7
6  ID2     A      7    8
7  ID2     B      8    9
8  ID2     B      9   10
9  ID2     B     11   12
    ID Group  Start  End
0  ID1     A      1    4
1  ID1     B      4    6
2  ID2     A      6    8
3  ID2     B      8   10
4  ID2     B     11   12