Объединить (и условно обновить) Pandas DataFrames - PullRequest
0 голосов
/ 27 июня 2019

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

Каждый раз, когда данные очищаются, они получают временную метку, но я не хочу перезаписывать временную метку при повторной очистке того же самого элемента данных (может быть идентифицирован по уникальным идентификаторам).
Кроме того, записи могут быть отмеченыкак active или неактивно , и если ранее active запись превращает неактивно в более позднюю очистку, это следует очистить в данных, добавивновая отметка времени, показывающая, когда предложение неактивно.

У меня есть следующие данные (df_total, df_new), которые я хотел бы объединить и обновить:

# df_total:
    ID Names        Timestamp  Active Inactive-Stamp
0  121     A  20190626-120000    True               
1  122     B  20190626-120000    True               
2  123     C  20190626-120000    True               

# df_new:
    ID Names        Timestamp  Active Inactive-Stamp
0  122     B  20190627-140000    True               
1  123     C  20190627-140000   False               
2  124     D  20190627-140000    True               

Что работает:
Само слияние и обновление работает благодаря следующему подходу:

def join_data(df_total, df_new):
    # Doing a full outer join
    df = df_total.merge(df_new, on=list(df_total), how='outer')

    # Drop real duplicates (e.g. ID:122, Name:B)
    df = df.drop_duplicates(subset=['ID', 'Active'], keep='first')

    # "Add" the timestamp for the now inactive entry
    df.loc[(df.duplicated(subset=['ID'],
                          keep='last') == True), 'Inactive-Stamp'] = "newTimeStamp"

    # Change `active` (from `True` to `False`)
    df.loc[(df.duplicated(subset=['ID'],
                          keep='last') == True), 'Active'] = False

    # Delete the new duplicate
    df = df[(df.duplicated(subset=['ID'],
                           keep='first') == False)]

    # Reset index of new Dataframe 
    df.reset_index(inplace=True, drop=True)
    return(df)

df_total = join_data(df_total, df_new)

Это приводит к объединению фреймов данных и обновлению записей, как запланировано:

    ID Names        Timestamp  Active Inactive-Stamp
0  121     A  20190626-120000    True               
1  122     B  20190626-120000    True               
2  123     C  20190626-120000   False   newTimeStamp
3  124     D  20190627-140000    True               

Что такоеПроблема:
Снова можно изменить записи на active = True.
Проблема в том, что некоторые пользователи деактивируют только свою запись, чтобы затем снова активировать ее (чтобы они снова отображались)в верхней части веб-сайта).
Таким образом, представленный выше метод должен снова работать с неактивными данными.Рассмотрим следующие (еще более новые) данные:

# df_newer:
    ID Names        Timestamp  Active Inactive-Stamp
0  123     C  20190628-160000    True               
1  125     E  20190628-160000    True               

Что я пробовал:
Я попытался изменить метод, добавив (для timestamp и active):

# Changing the Inactive-Stamp:
df.loc[(df.duplicated(subset=['ID'], keep='last') == True)
        &
        (df['Active'][df.duplicated(subset=['ID'], keep='last')==True] == True),
        'Inactive-Stamp'] = "Timestamp"

df.loc[(df.duplicated(subset=['ID'], keep='last') == True)
       &
       (df['Active'][df.duplicated(subset=['ID'], keep='last') =True] == False),
       'Inactive-Stamp'] = ""


# Changing the Active-Boolean
df.loc[(df.duplicated(subset=['ID'], keep='last')==True)
       &
       (df['Active'][df.duplicated(subset=['ID'], keep='last')==True]==True),
       'Active'] = False
df.loc[(df.duplicated(subset=['ID'], keep='last')==True)
       &
       (df['Active'][df.duplicated(subset=['ID'], keep='last')==True]==False),
       'Active'] = True

Я надеялся, что это создаст Inactive-Stamp только когда предложение было изменено на неактивно и удалит / заменит Inactive-Stamp только тогда, когда наоборот.
Очевидно, что это немедленно меняет каждый активный , который изменяется на неактивный обратно на активный .
Вот почему я подумал сделать эти представленные утверждения вif -условие, которое выглядит примерно так (псевдокод):

if (duplicate ID with different active & new entry is inactive):
    df['Active'] = False
    df['Inactive-Stamp'] = newTimeStamp
elif (duplicate ID with different active & new entry is active):
    df['Active'] = True
    df['Inactive-Stamp'] = ''

Но я также не знаю, как реализовать это if -условие в DataFrame pandas и комбинации df.loc -функции, ниявляется ли это хорошей практикой вообще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...