Как я могу исправить свой код pandas, чтобы он правильно сравнивал наблюдения из двух разных моментов времени?

#python #pandas

#python #pandas

Вопрос:

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

         Date  PersonId  Temperature  Weight  Height
0 2016-01-01       101           64     145     203
1 2016-01-02       101           72     155     163
2 2016-01-03       101           77     140     234
3 2016-01-04       101           88     130     182
4 2017-01-01       101           54     145     203
5 2017-01-02       101           62     155     163
6 2017-01-03       101           67     140     234
7 2017-01-04       101           78     130     182
  
 import pandas as pd
import sqlalchemy

#Create database connection
engine = sqlalchemy.create_engine('mysql pymysql://root:root@localhost:3306/mydb')

#Pull in database tables
Observations = pd.read_sql_table("observations", engine)
Observations['DateID'] = Observations['Date']   # Creating a second date column to use as part of multi-index while still preserving date column for manipulation
Observations.set_index(['PersonID', 'DateID'], inplace=True) #setting multi-index
Observations.sort_index(inplace=True)

# Calculate Alternative Dates
TemperatureLag = 12
TemperatureLagDate = Observations['Date'] - pd.DateOffset(months=TemperatureLag)

# Calculate derived metrics
PrevTemperature = Observations.loc[(slice(None), TemperatureLagDate), 'Temperature']

print(PrevTemperature)
  

К сожалению, когда я делаю это, он выдает мне столбец PrevTemperature, который совпадает с моим исходным столбцом температуры — так что против 1 января-17 он по-прежнему показывает 54 вместо того, что я ищу, чтобы показать NaN против 1 января-17 (потому что мои данные не имеют значения для1-Jan-16) и отобразить значение 54 против 1-Jan-18 (т. Е. Значение за один год до 1-Jan-18) для столбца PrevTemperature. Что я делаю не так?

Ответ №1:

Вы можете использовать df.merge для этого:

 # Get dataframe
Observations = pd.read_sql_table("observations", engine)
df = Observations

# Calculate previous date (I think shifting by number of days is more consistent)
df['Previous Date'] = df['Date'] - dt.timedelta(days=365)

# Merge the data onto itself
df = df.merge(
        right=df[['Date', 'Temperature']],
        how='left',
        left_on='Previous Date',
        right_on='Date',
        suffixes=(None, '_y')
    )

# Drop unneeded column and rename
df = df.drop(columns=['Date_y']).rename(columns={'Temperature_y':'Previous Temperature'})

# Calculate variation
df['% Temperature Variation'] = (df['Temperature'] / df['Previous Temperature'] - 1) * 100
  

Вывод:

         Date  PersonId  Temperature  Weight  Height Previous Date  Previous Temperature  % Temperature Variation
0 2016-01-01       101           64     145     203    2015-01-01                   NaN                      NaN
1 2016-01-02       101           72     155     163    2015-01-02                   NaN                      NaN
2 2016-01-03       101           77     140     234    2015-01-03                   NaN                      NaN
3 2016-01-04       101           88     130     182    2015-01-04                   NaN                      NaN
4 2017-01-01       101           54     145     203    2016-01-02                  72.0               -25.000000
5 2017-01-02       101           62     155     163    2016-01-03                  77.0               -19.480519
6 2017-01-03       101           67     140     234    2016-01-04                  88.0               -23.863636
7 2017-01-04       101           78     130     182    2016-01-05                   NaN                      NaN