Панды, выберите значения из столбца, где значение в другом столбце выше, чем другое значение в том же столбце

#python-3.x #pandas #dataframe

Вопрос:

У меня есть фрейм данных Pandas с идентификатором столбцов,событием,меткой времени.

Я хочу выбрать все идентификаторы, в которых отметка времени события A больше, чем отметка времени события B того же идентификатора

 id event timestamp
1    a      2021-01-25 10:16:46 
1    b      2021-01-22 10:16:46 
2    a      2021-01-25 10:16:46 
2    b      2021-01-28 10:16:46 
3    a      2021-01-25 10:16:46 
3    b      2021-01-25 11:16:46 
 

Таким образом, в приведенном выше фрейме данных только идентификатор 1 содержит событие a, которое больше, чем событие b, поэтому мне нужен только список, содержащий идентификатор 1.

Я попробовал следующий код ниже:

 df = pd.read_csv("data.csv")
df = df.sort_values(by=["id", "event"])
df.astype({'timestamp': 'datetime64'}).dtypes

ids = []

for s in df["id"]:
    y = df.query("event == 'a' amp; id ==  @s").iloc[0,2] #select a timestamp
    z = df.query("event == 'b' amp; id ==  @s").iloc[0,2] #select b timestamp
    a = pd.to_datetime(y) #convert to timestamp so can compare
    b = pd.to_datetime(z)
    if sample in ids: #remove duplicate from entering the list
        pass
    elif a > b:
        ids.append(s) #add to list
    else:
        pass

print((len(ids))) #give count of unique ids
 

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

Спасибо

Ответ №1:

Используйте DataFrame.pivot для сравнения обоих столбцов с фильтром id из df1.index :

 df = pd.read_csv("data.csv", parse_dates='timestamp')

df1 = df.pivot('id','event','timestamp')
print (df1)
event                   a                   b
id                                           
1     2021-01-25 10:16:46 2021-01-22 10:16:46
2     2021-01-25 10:16:46 2021-01-28 10:16:46
3     2021-01-25 10:16:46 2021-01-25 11:16:46


ids = df1.index[df1['a'] > df1['b']].tolist()
print (ids)
[1]
 

Комментарии:

1. Привет, спасибо за помощь, я никогда не думал использовать pivot. Я пытался, но я продолжаю получать ошибку ValueError: индекс содержит повторяющиеся записи, не может измениться. Есть идеи, почему это может быть?

2. Используйте df1 = df.pivot_table(index='id',columns='event',values='timestamp', aggfunc='max') — нужны агрегированные значения, если они дублируются.

3. Ах, большое спасибо, это сработало идеально!