Масштабируемое нормальное распределение Python от pandas DataFrame

У меня есть кадр данных pandas (код ниже), который имеет среднее и стандартное отклонение по дням недели и кварталам. Что я хотел бы сделать, так это извлечь каждое среднее значение и стандартное отклонение по дням недели, создать случайную нормальную выборку из этих двух значений, а затем построить ее.

np.random.seed(42)
day_of_week=['mon', 'tues', 'wed', 'thur', 'fri', 'sat','sun']
year=[2017]
qtr=[1,2,3,4]
mean=np.random.uniform(5,30,len(day_of_week)*len(qtr))
std=np.random.uniform(1,10,len(day_of_week)*len(qtr))

dat=pd.DataFrame({'year':year*(len(day_of_week)*len(qtr)),
             'qtr':qtr*len(day_of_week),
             'day_of_week':day_of_week*len(qtr),
             'mean':mean,
             'std': std})
dowuq=dat.day_of_week.unique()

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

Код, который работает, но не масштабируется:

plt.style.use('fivethirtyeight')
for w in dowuq:
    datsand=dat[dat['day_of_week']==''+str(w)+''][0:4]
    mu=datsand.iloc[0]['mean']
    sigma=datsand.iloc[0]['std']
    mu2=datsand.iloc[1]['mean']
    sigma2=datsand.iloc[1]['std']
    mu3=datsand.iloc[2]['mean']
    sigma3=datsand.iloc[2]['std']
    mu4=datsand.iloc[3]['mean']
    sigma4=datsand.iloc[3]['std']             
    s1=np.random.normal(mu, sigma, 2000)
    s2=np.random.normal(mu2, sigma2, 2000)
    s3=np.random.normal(mu3, sigma3, 2000)
    s4=np.random.normal(mu4, sigma4, 2000)
    sns.kdeplot(s1, bw='scott', label='Q1')
    sns.kdeplot(s2, bw='scott', label='Q2')
    sns.kdeplot(s3, bw='scott', label='Q3')
    sns.kdeplot(s4, bw='scott', label='Q4')
    plt.title(''+str(w)+' in 2017')
    plt.ylabel('Density')
    plt.xlabel('Random')
    plt.xticks(rotation=15)
    plt.show()

person P.Cummings    schedule 21.07.2017    source источник


Ответы (1)


Вероятно, вам следует использовать groupby, который позволяет группировать фрейм данных. В настоящее время мы группируем только 'day', но вы можете расширить это в будущем, если потребуется.

Мы также можем использовать iterrows для цикл по всем перечисленным строкам:

import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

np.random.seed(42)
day_of_week = ['mon', 'tues', 'wed', 'thur', 'fri', 'sat', 'sun']
year = [2017]
qtr = [1, 2, 3, 4]
mean = np.random.uniform(5, 30, len(day_of_week) * len(qtr))
std = np.random.uniform(1, 10, len(day_of_week) * len(qtr))

dat = pd.DataFrame({'year': year * (len(day_of_week) * len(qtr)),
                    'qtr': qtr * len(day_of_week),
                    'day_of_week': day_of_week * len(qtr),
                    'mean': mean,
                    'std': std})

# Group by day of the week
for day, values in dat.groupby('day_of_week'):
    # Loop over rows for each day of the week
    for i, r in values.iterrows():
        cur_dist = np.random.normal(r['mean'], r['std'], 2000)
        sns.kdeplot(cur_dist, bw='scott', label='{}_Q{}'.format(day, r['qtr']))
    plt.title('{} in 2017'.format(day))
    plt.ylabel('Density')
    plt.xlabel('Random')
    plt.xticks(rotation=15)
    plt.show()
    plt.clf()
person asongtoruin    schedule 21.07.2017
comment
Спасибо за это. Для моего собственного пояснения, данные уже находятся на уровне дня недели, зачем вам группировать по дням недели? - person P.Cummings; 21.07.2017
comment
группировка по дням недели эффективно объединяет то, что вы называете dowuq и datsand. Для каждого уникального значения в столбце 'day_of_week' groupby предоставляет кадр данных, состоящий только из строк, соответствующих этому значению. Вы можете попробовать напечатать values внутри первого цикла for, чтобы увидеть это более четко. - person asongtoruin; 21.07.2017
comment
@P.Cummings помогает ли это решить вашу проблему? - person asongtoruin; 21.07.2017
comment
@P.Cummings всегда пожалуйста! Если он вам помог, вы можете отметить его как ответ и/или проголосовать за него, используя кнопки слева от ответа, что должно помочь людям с похожими проблемами найти его в будущем. - person asongtoruin; 21.07.2017