#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