Chcę wykonać kroczącą medianę w kolumnie ceny z 4 dni wstecz, dane zostaną pogrupowane według daty. Więc zasadniczo chcę wziąć ceny z danego dnia i wszystkie ceny z 4 dni wstecz i obliczyć medianę z tych wartości.

Oto przykładowe dane:

id      date        price
1637027 2020-01-21  7045204.0
280955  2020-01-11  3590000.0
782078  2020-01-28  2600000.0
1921717 2020-02-17  5500000.0
1280579 2020-01-23  869000.0
2113506 2020-01-23  628869.0
580638  2020-01-25  650000.0
1843598 2020-02-29  969000.0
2300960 2020-01-24  5401530.0
1921380 2020-02-19  1220000.0
853202  2020-02-02  2990000.0
1024595 2020-01-27  3300000.0
565202  2020-01-25  3540000.0
703824  2020-01-18  3990000.0
426016  2020-01-26  830000.0

Zbliżyłem się do połączenia toczenia i grupowania:

df.groupby('date').rolling(window = 4, on = 'date')['price'].median()

Ale wydaje się, że dodaje to jeden wiersz na każdą wartość indeksu i zgodnie z definicją mediany nie jestem w stanie w jakiś sposób scalić tych wierszy, aby uzyskać jeden wynik na wiersz.

Wynik wygląda teraz tak:

date        date      
2020-01-10  2020-01-10          NaN
            2020-01-10          NaN
            2020-01-10          NaN
            2020-01-10    3070000.0
            2020-01-10    4890000.0
                            ...    
2020-03-11  2020-03-11    4290000.0
            2020-03-11    3745000.0
            2020-03-11    3149500.0
            2020-03-11    3149500.0
            2020-03-11    3149500.0
Name: price, Length: 389716, dtype: float64

Wygląda na to, że po prostu usunął 3 pierwsze wartości, a następnie po prostu wydrukował wartość ceny.

Czy można uzyskać jedną opóźnioną / ruchomą medianę na jedną datę?

1
Musisak 26 marzec 2020, 00:09

2 odpowiedzi

Najlepsza odpowiedź

Możesz użyć rolling z pięciodniowym przedziałem częstotliwości, aby otrzymać dzień dzisiejszy i ostatnie 4 dni, a następnie drop_duplicates, aby zachować ostatni wiersz na dzień. Najpierw utwórz copy (jeśli chcesz zachować oryginał), sort_values według daty i upewnij się, że kolumna z datą to data i godzina

#sort and change to datetime
df_f = df[['date','price']].copy().sort_values('date')
df_f['date'] = pd.to_datetime(df_f['date'])

#create the column rolling
df_f['price'] = df_f.rolling('5D', on='date')['price'].median()

#drop_duplicates and keep the last row per day
df_f = df_f.drop_duplicates(['date'], keep='last').reset_index(drop=True)

print (df_f)

         date      price
0  2020-01-11  3590000.0
1  2020-01-18  3990000.0
2  2020-01-21  5517602.0
3  2020-01-23   869000.0
4  2020-01-24  3135265.0
5  2020-01-25  2204500.0
6  2020-01-26   849500.0
7  2020-01-27   869000.0
8  2020-01-28  2950000.0
9  2020-02-02  2990000.0
10 2020-02-17  5500000.0
11 2020-02-19  3360000.0
12 2020-02-29   969000.0
2
Ben.T 26 marzec 2020, 01:03

To jest proces krok po kroku. Prawdopodobnie istnieją skuteczniejsze metody zdobywania tego, czego chcesz. Uwaga, jeśli masz informacje o czasie dla swoich dat, musisz je usunąć przed grupowaniem według daty.

import pandas as pd
import statistics as stat
import numpy as np

# Replace with you data import
df = pd.read_csv('random_dates_prices.csv')

# Convert your date to a datetime
df['date'] = pd.to_datetime(df['date'])

# Sort your data by date
df = df.sort_values(by = ['date'])

# Create group by object
dates = df.groupby('date')

# Reformat dataframe for one row per day, with prices in a nested list
df = pd.DataFrame(dates['price'].apply(lambda s: s.tolist()))

# Extract price lists to a separate list
prices = df['price'].tolist()

# Initialize list to store past four days of prices for current day
four_days = []

# Loop over the prices list to combine the last four days to a single list
for i in range(3, len(prices), 1):
    x = i - 1
    y = i - 2
    z = i - 3
    four_days.append(prices[i] + prices[x] + prices[y] + prices[z])

# Initialize a list to store median values
medians = []

# Loop through four_days list and calculate the median of the last for days for the current date
for i in range(len(four_days)):
    medians.append(stat.median(four_days[i]))

# Create dummy zero values to add lists create to dataframe    
four_days.insert(0, 0)
four_days.insert(0, 0)
four_days.insert(0, 0)
medians.insert(0, 0)
medians.insert(0, 0)
medians.insert(0, 0)

# Add both new lists to data frames
df['last_four_day_prices'] = four_days
df['last_four_days_median'] = medians

# Replace dummy zeros with np.nan
df[['last_four_day_prices', 'last_four_days_median']] = df[['last_four_day_prices', 'last_four_days_median']].replace(0, np.nan)

# Clean data frame so you only have a single date a median value for past four days
df_clean = df.drop(['price', 'last_four_day_prices'], axis=1)
1
Michael Longstreth 26 marzec 2020, 03:51