Modeling the Joint Distribution of Wind Speed and Direction using Gaussain Mixture Models

OEN Method: Harris, Cook The parent wind speed distribution: Why Weibull? http://www.sciencedirect.com/science/article/pii/S0167610514001056

Gaussian Mixture Models, http://scikit-learn.org/stable/modules/mixture.html

1. Set up

1.1 Environment

In [1]:
%matplotlib inline
%load_ext autoreload
%autoreload 2

from import_file import *
from helpers.parallel_helper import *
load_libs()

plt.rcParams['axes.autolimit_mode'] = 'round_numbers'
plt.rcParams['axes.xmargin'] = 0.
plt.rcParams['axes.ymargin'] = 0.
mpl.rcParams['patch.force_edgecolor'] = True

1.2 Read Data

In [2]:
# file_path, bandwidth= './data/NCDC/europe/uk/marham/dat.txt', 1.7
# file_path, bandwidth= './data/NCDC/europe/uk/tiree/dat.txt', 1.9
# file_path, bandwidth, NUMBER_OF_GAUSSIAN = './data/NCDC/europe/uk/boscombe_down/dat.txt', 1.5, 4
# file_path, bandwidth= './data/NCDC/europe/uk/middle_wallop/dat.txt', 1.3
# file_path, bandwidth= './data/NCDC/europe/uk/bournemouth/dat.txt',1.3 # 4?
# file_path= "./data/NCDC/europe/uk/weybourne/dat.txt"
# file_path= "./data/NCDC/europe/uk/skye_lusa/dat.txt" # 
# file_path= "./data/NCDC/europe/uk/wattisham/dat.txt"
# file_path= "./data/NCDC/europe/uk/south_uist_range/dat.txt" # inpropoer direction R square measure
# file_path= "./data/NCDC/europe/uk/holbeach/dat.txt" # inpropoer direction R square measure
# file_path= "./data/NCDC/europe/uk/cambridge/dat.txt" # inpropoer direction R square measure
# file_path= "./data/NCDC/europe/us/baltimore/dat.txt" # time too short
# file_path= "./data/NCDC/europe/uk/bealach_na_ba/dat.txt" # time too short
# file_path= "./data/NCDC/europe/uk/benbecula/dat.txt" # truncate (untruncate in m/s), 4?
# file_path= './data/NCDC/europe/uk/southhamption/dat.txt' # high 0, trend

# file_path, bandwidth, NUMBER_OF_GAUSSIAN = "./data/NCDC/europe/germany/landsberg_lech/dat.txt", 0.9, 4 
# file_path, bandwidth= "./data/NCDC/europe/germany/neuburg/dat.txt", 0.7
# file_path, bandwidth= "./data/NCDC/europe/germany/laupheim/dat.txt", 0.7 # double peak, 4?, trend
# file_path, bandwidth= './data/NCDC/europe/germany/niederstetten/dat.txt', 0.9 # get the peak
# file_path, bandwidth= "./data/NCDC/europe/germany/holzdorf/dat.txt", 0.9 # 2008 year
# file_path, bandwidth, NUMBER_OF_GAUSSIAN= './data/NCDC/europe/france/nantes/dat.txt', 0.9, 4 # unit shift, one direction deviate big
# file_path, convert_to_knot= './data/NCDC/europe/france/pau_pyrenees/dat.txt', True # unit shift, 2; force using knot 
# file_path= "./data/NCDC/europe/france/avord/dat.txt" # try 4, initial speed (should be good with m/s), incompete dataset
# file_path= "./data/NCDC/europe/france/vatry/dat.txt"  # double peak, initial speed, incompete dataset
# file_path, bandwidth, NUMBER_OF_GAUSSIAN= "./data/NCDC/europe/spain/valladolid/dat.txt", 1.1, 4
# file_path= './data/NCDC/europe/spain/jerez/dat.txt' # high 0
# file_path, bandwidth= "./data/NCDC/europe/spain/barayas/dat.txt", 0.7 # not good fit
# file_path, bandwidth= './data/NCDC/europe/spain/malaga/dat.txt', 0.7 # directions blocked?
# file_path, bandwidth= './data/NCDC/europe/spain/tenerife_sur/dat.txt', 0.7 # directions blocked?
# file_path, bandwidth= './data/NCDC/europe/spain/almeria/dat.txt', 0.7 # negative dimensions?
# file_path, bandwidth= './data/NCDC/europe/greece/eleftherios_intl/dat.txt',0.7 # some direction might be blocked
# file_path= './data/NCDC/europe/ciampino/dat.txt' # try 4, bandwidth?
# file_path= "./data/NCDC/europe/huspel_aws/dat.txt"  # integer, 4?
# file_path= './data/NCDC/gibraltar/dat.txt' # bad fit

# MidEast
# file_path, bandwidth= './data/NCDC/mideast/uae/al_maktoum/dat.txt', 1.1
# file_path= './data/NCDC/mideast/uae/sharjah_intl/dat.txt' 
# file_path= './data/NCDC/mideast/uae/dubai_intl/dat.txt' 
# file_path= './data/NCDC/mideast/uae/abu_dhabi_intl/dat.txt' # Time shift
# file_path= './data/NCDC/mideast/uae/bateen/dat.txt' # Time shift
# file_path= './data/NCDC/mideast/buraimi/dat.txt' # not good dataset
# file_path= './data/NCDC/mideast/turkey/konya/dat.txt' 
# file_path= './data/NCDC/mideast/turkey/sivas/dat.txt' # bad dataset
# file_path= './data/NCDC/mideast/turkey/balikesir/dat.txt' # bad dataset
# file_path= './data/NCDC/mideast/turkey/bartin/dat.txt' # bad dataset
# file_path= './data/NCDC/mideast/iran/chahbahar/dat.txt'
# file_path= './data/NCDC/mideast/iran/zabol/dat.txt' # Problematic data
# file_path= './data/NCDC/mideast/iran/torbat_heydarieh/dat.txt' # Unusable

file_path, bandwidth = "./data/NCDC/cn/shanghai/hongqiao_intl/dat.txt", 0.6
# file_path, bandwidth= "./data/NCDC/cn/shanghai/pudong/dat.txt", 0.8
# file_path, bandwidth= "./data/NCDC/cn/hefei_luogang/dat.txt", 0.6 # few 0, trend
# file_path, bandwidth= "./data/NCDC/cn/nanjing_lukou/dat.txt", 0.5
# file_path= "./data/NCDC/cn/zhengzhou_xinzheng/dat.txt" 
# file_path= "./data/NCDC/cn/tianjin/binhai/dat.txt" # few 0, trend, stationary speed, unstationary direction
# file_path= "./data/NCDC/cn/tianjin/tianjing/dat.txt" # 16 sectors
# file_path= "./data/NCDC/cn/shijiazhuang_zhengding/dat.txt" 
# file_path= "./data/NCDC/cn/henan_gushi/dat.txt" # 16 sectors, fit not very good
# file_path= "./data/NCDC/cn/nanning_wuxu/dat.txt" # numpy priblem, unstationary speed
# file_path= './data/NCDC/cn/macau/dat.txt'  
# file_path= "./data/NCDC/cn/hk_intl/dat.txt" # few 0
# file_path= './data/NCDC/cn/gaoqi/dat.txt' 

# file_path= './data/NCDC/southeast_asia/malaysia/mersing/dat.txt' # 2 mode, paper comparison
# file_path= './data/NCDC/southeast_asia/malaysia/penang/dat.txt'
# file_path= './data/NCDC/southeast_asia/malaysia/butterworth/dat.txt' # 2 mode 
# file_path= "./data/NCDC/southeast_asia/malaysia/bsultan_mahmud/dat.txt" # stable
# file_path= "./data/NCDC/southeast_asia/malaysia/bsultan_ismail/dat.txt" # 
# file_path= "./data/NCDC/southeast_asia/singapore/changi/dat.txt" # trend, no 0, questionary data
# file_path= "./data/NCDC/southeast_asia/singapore/paya_lebar/dat.txt" # questionary data
# file_path= "./data/NCDC/southeast_asia/singapore/seletar/dat.txt"
# file_path= "./data/NCDC/east_asia/cheongju_intl/dat.txt" # 2005-2009  may have problem, fit is good; numpy problem
# file_path= "./data/NCDC/east_asia/daegu_ab/dat.txt" # recent 5 year may have problem, but fit is generally good; numpy problem

# file_path, bandwidth= "./data/NCDC/oceania/auckland_intl/dat.txt", 0.9  # Good data, double mode
# file_path= "./data/NCDC/oceania/brisbane_archerfield/dat.txt" # high 0, few data 
# file_path= "./data/NCDC/oceania/narrandera/dat.txt" # high 0, few data
# file_path, bandwidth= "./data/NCDC/oceania/canberra/dat.txt", 0.7 # high 0, bad fit
# file_path, bandwidth, NUMBER_OF_GAUSSIAN= './data/NCDC/oceania/horsham/dat.txt', 0.9, 4 # get the peak

# file_path, bandwidth= './data/NCDC/us/boston_16nm/dat.txt', 0.9 # Offshore, mixed type

# file_path, bandwidth, NUMBER_OF_GAUSSIAN  = './data/asos/bismarck_ND/hr_avg.csv', 1.1, 4
# file_path, bandwidth, NUMBER_OF_GAUSSIAN = './data/asos/aberdeen_SD/hr_avg.csv', 1.7, 2 # only to 2012
# file_path, bandwidth, NUMBER_OF_GAUSSIAN = './data/asos/minneapolis/hr_avg.csv', 1.1, 4
# file_path, bandwidth = './data/asos/lincoln_NE/hr_avg.csv', 0.9
# file_path, bandwidth = './data/asos/des_moines_IA/hr_avg.csv', 1.3
# file_path, bandwidth = './data/asos/springfield_IL/hr_avg.csv', 1.1 
# file_path, bandwidth = './data/asos/topeka/hr_avg.csv', 0.7 # High 0
# file_path, bandwidth = './data/asos/denver/hr_avg.csv', 1.3
# file_path, bandwidth= './data/asos/olympia/hr_avg.csv', 0.5 # might block

# file_path, bandwidth, NUMBER_OF_GAUSSIAN = './data/NDAWN/baker/hr_avg.csv', 0.7, 4 
# file_path, bandwidth = './data/NDAWN/dickinson/hr_avg.csv', 0.6
# file_path = './data/NDAWN/rugby/hr_avg.csv'
# file_path = './data/NDAWN/bowman/hr_avg.csv'
# file_path = './data/NDAWN/grand_forks/hr_avg.csv'
# file_path = './data/NDAWN/williston/hr_avg.csv'
# file_path = './data/NDAWN/jamestown/hr_avg.csv'

# file_path, bandwidth, NUMBER_OF_GAUSSIAN = 'data/ECMWF/usa/47N123W/dat.csv', 0.7, 4 #good 
# file_path, bandwidth = 'data/ECMWF/venezuela/8N67W/dat.csv', 0.7 # good, but the data might be problematic.
# file_path, bandwidth = 'data/ECMWF/chile/52S75W/dat.csv', 1.9 # good
# file_path, bandwidth= 'data/ECMWF/iceland/65N17W/dat.csv', 1.9 # good
# file_path, bandwidth, NUMBER_OF_GAUSSIAN  = 'data/ECMWF/germany/49N9E/dat.csv', 0.9, 4 # good
# file_path, bandwdith = 'data/ECMWF/sudan/18N32E/dat.csv', 1.1 # good
# file_path, bandwidth = 'data/ECMWF/china/24N121E/dat.csv', 0.9 # good
# file_path, bandwidth, NUMBER_OF_GAUSSIAN = 'data/ECMWF/australia/37S142E/dat.csv', 0.7, 4 # miss the peak, force bandwidth 0.7, default 0.9
In [3]:
if "cn_database" in file_path: 
    df = read_cn_database(file_path)
elif 'NCDC' in file_path:
    df = pd.read_csv(file_path, header=0, skipinitialspace=True, dtype={'HrMn':'object'})
    df.rename(columns={'Date':'date','Dir':'dir','Spd':'speed','Type':'type','I.1':'wind_type'}, inplace=True)
    df = df[['date','HrMn','type','dir','speed','wind_type' ]]
    df.dropna(subset=['dir','speed'], inplace=True)
    integer_data = True
elif 'NDAWN' in file_path:
    df = pd.read_csv(file_path, header=0, skipinitialspace=True, dtype={'HrMn':'object'})
    df['type']='default'
    df['wind_type']='default'
    df = df.dropna()
    convert_to_knot = False
    integer_data = False
elif 'asos' in file_path:
    # ASOS
    df = pd.read_csv(file_path, header=0, skipinitialspace=True, dtype={'HrMn':'object'})
    df['type']='default'
    df['wind_type']='default'
    df = df.dropna()
    convert_to_knot = False
    integer_data = False
    knot_unit = True
else:
    df = pd.read_csv(file_path, header=0, skipinitialspace=True)
    df.rename(columns={'U':'x','V':'y'}, inplace=True)
    df.x=-df.x
    df.y=-df.y
    df['speed']=np.sqrt(df.x**2+df.y**2)
    df['dir']=np.degrees(np.arctan2(df.y, df.x))%360
    df['time']=pd.to_datetime('1979-01-01T00:00:00Z')+pd.to_timedelta(df['time'], unit='h')
    df['date']=df['time'].dt.strftime('%Y%m%d')
    df['date']=df['date'].astype(int)
    df['HrMn']=df['time'].dt.strftime('%H00')
    df['type']='default'
    df['wind_type']='default'
    convert_to_knot = True
    integer_data = False
    cartesian = True
In [4]:
df
Out[4]:
date HrMn type dir speed wind_type
0 19560820 0000 FM-12 200 5.1 N
1 19560820 0300 FM-12 250 4.1 N
2 19560820 0600 FM-12 250 5.1 N
3 19560820 0900 FM-12 270 6.2 N
4 19560820 1200 FM-12 270 5.1 N
5 19560820 1800 FM-12 290 3.1 N
6 19560820 2100 FM-12 320 3.1 N
7 19560821 0000 FM-12 320 3.1 N
8 19560821 0300 FM-12 290 4.1 N
9 19560821 0600 FM-12 270 5.1 N
10 19560821 0900 FM-12 320 2.1 N
11 19560821 1200 FM-12 90 1.0 N
12 19560821 1800 FM-12 140 2.1 N
13 19560821 2100 FM-12 140 2.1 N
14 19560822 0300 FM-12 140 6.2 N
15 19560822 0600 FM-12 160 4.1 N
16 19560822 1200 FM-12 140 4.1 N
17 19560822 1800 FM-12 200 3.1 N
18 19560822 2100 FM-12 290 7.2 N
19 19560823 0300 FM-12 270 7.2 N
20 19560823 0900 FM-12 320 5.1 N
21 19560823 1200 FM-12 270 1.0 N
22 19560823 2100 FM-12 999 0.0 C
23 19560824 0000 FM-12 999 0.0 C
24 19560824 0300 FM-12 270 1.0 N
25 19560824 0600 FM-12 90 1.0 N
26 19560824 0900 FM-12 160 2.1 N
27 19560824 1200 FM-12 999 0.0 C
28 19560824 1800 FM-12 999 0.0 C
29 19560824 2100 FM-12 140 4.1 N
... ... ... ... ... ... ...
359333 20150301 0900 FM-15 270 4.0 N
359334 20150301 0930 FM-15 260 4.0 V
359335 20150301 1000 FM-15 250 4.0 V
359336 20150301 1030 FM-15 250 3.0 V
359337 20150301 1100 FM-15 260 4.0 N
359338 20150301 1130 FM-15 230 3.0 N
359339 20150301 1200 FM-15 230 2.0 V
359340 20150301 1230 FM-15 270 3.0 N
359341 20150301 1300 FM-15 240 2.0 V
359342 20150301 1330 FM-15 260 2.0 V
359343 20150301 1400 FM-15 250 2.0 V
359344 20150301 1430 FM-15 240 2.0 V
359345 20150301 1500 FM-15 999 0.0 C
359346 20150301 1530 FM-15 999 1.0 V
359347 20150301 1600 FM-15 999 1.0 V
359348 20150301 1630 FM-15 210 1.0 N
359349 20150301 1700 FM-15 999 1.0 V
359350 20150301 1730 FM-15 999 1.0 V
359351 20150301 1800 FM-15 999 1.0 V
359352 20150301 1830 FM-15 180 1.0 N
359353 20150301 1900 FM-15 160 1.0 N
359354 20150301 1930 FM-15 210 1.0 N
359355 20150301 2000 FM-15 230 2.0 N
359356 20150301 2030 FM-15 230 1.0 N
359357 20150301 2100 FM-15 240 2.0 N
359358 20150301 2130 FM-15 180 1.0 N
359359 20150301 2200 FM-15 160 1.0 N
359360 20150301 2230 FM-15 150 1.0 N
359361 20150301 2300 FM-15 190 2.0 N
359362 20150301 2330 FM-15 190 1.0 N

359363 rows × 6 columns

In [5]:
if 'NCDC' in file_path:
    lat, long = get_lat_long(file_path)
    print(lat,long)
    map_osm = folium.Map(location=[lat, long], zoom_start=4)
    folium.Marker([lat, long]).add_to(map_osm)
    display(map_osm)
31.198 121.336
In [6]:
df['time']=pd.to_datetime(df["date"].astype(str).map(str) + df["HrMn"], format='%Y%m%d%H%M')
df.set_index(['time'], inplace=True)
df['HrMn']=df['HrMn'].astype(int)
df = df.query("(dir <= 999) & (speed < 100) ")['1970':'2016']
In [7]:
plot_speed_and_angle_distribution(df.speed, df.dir)
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\__init__.py:938: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
  warnings.warn(self.msg_depr % (key, alt_key))
In [8]:
# Dir [10,360]=> [0,350]
df['dir'] = df['dir'].apply(lambda x: x%360 if x < 999 else x) 
# Convert Windrose coordianates to Polar Cooridinates 
if 'cartesian' in globals():
    df['dir_windrose'] = df['dir'].apply(lambda x: (90 - x)%360 if x < 999 else x)
else:
    df['dir_windrose'] = df['dir']
    df['dir'] = df['dir'].apply(lambda x: (90 - x)%360 if x < 999 else x)
display(df.describe())
df.plot(y='speed',legend=True,figsize=(20,5))
date HrMn dir speed dir_windrose
count 3.369710e+05 336971.000000 336971.000000 336971.000000 336971.000000
mean 2.000006e+07 1128.070137 268.228497 3.543890 248.807883
std 1.115119e+05 691.735348 275.924866 2.002307 279.529540
min 1.973010e+07 0.000000 0.000000 0.000000 0.000000
25% 1.991120e+07 530.000000 90.000000 2.000000 90.000000
50% 2.002062e+07 1100.000000 200.000000 3.000000 150.000000
75% 2.010050e+07 1730.000000 320.000000 5.000000 310.000000
max 2.015030e+07 2357.000000 999.000000 30.000000 999.000000
Out[8]:
<matplotlib.axes._subplots.AxesSubplot at 0xcda7208>

1.3 General Data Info

1.3.1 Unit Detection

In [9]:
df['decimal'] = df.speed % 1
df.decimal.hist(alpha=0.5, label='m/s', figsize=(4, 3))

if 'convert_to_knot' not in globals():
    convert_to_knot = True if len(df.query('decimal >= 0.2')) / len(df) > 0.3 else False
    
if convert_to_knot:
    knot_unit = True
    df['speed'] = df['speed'] * 1.943845
    df['decimal'] = df.speed % 1
    df.decimal.hist(alpha=0.5, label='knot')
    # need more elaboration, some is not near an integer
    if integer_data:
        df['speed'] = df['speed'].apply(lambda x: int(round(x)))
    plt_configure(xlabel='Decimal', ylabel='Frequency', legend={'loc': 'best'}, title='Decimal Distribution')
else:
    if 'knot_unit' not in globals():
        knot_unit = False
    
df.drop(['decimal'], 1,inplace=True)
print(knot_unit)
False
In [10]:
dir_unit_text = ' (degree)'
if knot_unit == True:
    speed_unit_text = ' (knot)'
else: 
    speed_unit_text = ' (m/s)'

1.3.2 Sampling Type Selection

In [11]:
sample_type = df.query('date > 20000000')['type']
sample_type.value_counts().plot(
    kind = 'bar', title = 'Report Types Comprisement', figsize=(4,3))

report_type_most_used = sample_type.value_counts().argmax()
df = df.query("type==@report_type_most_used")

1.3.3 Sampling Time Selection

In [12]:
MID_YEAR = int(np.average(df.index.year))

df['HrMn'].value_counts().sort_index().plot(kind='bar', alpha=0.5,label='Overall')
df[str(MID_YEAR):]['HrMn'].value_counts().sort_index().plot(
    kind='bar', alpha=0.5, label='>= %s' %  MID_YEAR )

plt_configure(xlabel='Sampling Time', ylabel='Frequency', legend={'loc':'best'}, figsize=(8, 4), 
              title = 'Sampling Time Distribution, Overall and > %s ' %  MID_YEAR)
In [13]:
df['sample_time'] = df.HrMn % 100 
sample_time = df['2000':]['sample_time']
sample_times = sample_time.value_counts()[sample_time.value_counts() > 2000]
sample_times = sample_times.index.tolist()
# df = df.query("sample_time in @sample_times")
df = df.query("sample_time == @sample_times[0]")
df.drop(['sample_time'], 1,inplace=True)
print(sample_times)

df['HrMn'].value_counts().sort_index().plot(kind='bar', alpha=0.5, figsize=(10, 4))
[0, 30]
Out[13]:
<matplotlib.axes._subplots.AxesSubplot at 0x14989e10>

1.4 Error Data handling and Adjustment

1.4.1 Artefacts

wrong direction record

In [14]:
if integer_data:
    display(df.query("(dir % 10 >= 0.1) & (dir != 999)"))
    df = df.query('(dir % 10 <= 0.1) | (dir == 999)')
date HrMn type dir speed wind_type dir_windrose
time
1994-01-28 00:00:00 19940128 0 FM-15 119 3.0 N 331
1994-07-18 10:00:00 19940718 1000 FM-15 337 5.0 N 113
1994-08-05 11:00:00 19940805 1100 FM-15 335 9.0 N 115
1994-08-10 05:00:00 19940810 500 FM-15 319 10.0 N 131
1994-09-03 21:00:00 19940903 2100 FM-15 331 5.0 N 119
1994-12-03 14:00:00 19941203 1400 FM-15 316 3.0 N 134
1995-04-03 13:00:00 19950403 1300 FM-15 337 3.0 N 113
1998-06-03 11:00:00 19980603 1100 FM-15 59 10.0 N 31
1998-09-09 12:00:00 19980909 1200 FM-15 359 20.0 N 91

sudden increase in speed

In [15]:
# sudden increse
df['incre'] = df.speed.diff(1)
df['incre'].fillna(0, inplace=True)
df['incre_reverse'] = df.speed.diff(-1)
df['incre_reverse'].fillna(0, inplace=True)

display(df.sort_values(by='speed',ascending=False).head(10))
df['incre'].plot(kind='hist', bins=arange(-15, 15), legend=True, figsize=(8, 3))
date HrMn type dir speed wind_type dir_windrose incre incre_reverse
time
1993-12-21 22:00:00 19931221 2200 FM-15 110 22.0 N 340 19.0 20.0
1993-08-02 14:00:00 19930802 1400 FM-15 140 21.0 N 310 17.0 21.0
1985-04-30 08:00:00 19850430 800 FM-15 310 16.0 N 140 9.8 9.8
2005-09-11 17:00:00 20050911 1700 FM-15 0 16.0 N 90 4.0 4.0
1981-12-19 07:00:00 19811219 700 FM-15 140 15.9 N 310 13.9 3.1
1994-10-20 08:00:00 19941020 800 FM-15 140 15.0 N 310 6.0 8.0
2012-08-08 05:00:00 20120808 500 FM-15 10 15.0 N 80 0.0 2.0
1995-11-07 04:00:00 19951107 400 FM-15 110 15.0 N 340 5.0 2.0
2012-08-08 04:00:00 20120808 400 FM-15 0 15.0 N 90 2.0 0.0
2008-07-02 08:00:00 20080702 800 FM-15 170 15.0 N 280 10.0 13.0
Out[15]:
<matplotlib.axes._subplots.AxesSubplot at 0xce670b8>
In [16]:
incre_threshold = 20 if knot_unit else 10
print('sudden increase number', len(df.query('(incre > @incre_threshold )&(incre_reverse > @incre_threshold )')))
df = df.query('(incre < @incre_threshold )|(incre_reverse < @incre_threshold )')

# Check the max speed
display(df.sort_values(by='speed',ascending=False).head(10))
df.drop(['incre', 'incre_reverse'], 1, inplace=True)
sudden increase number 2
date HrMn type dir speed wind_type dir_windrose incre incre_reverse
time
2005-09-11 17:00:00 20050911 1700 FM-15 0 16.0 N 90 4.0 4.0
1985-04-30 08:00:00 19850430 800 FM-15 310 16.0 N 140 9.8 9.8
1981-12-19 07:00:00 19811219 700 FM-15 140 15.9 N 310 13.9 3.1
2012-08-08 04:00:00 20120808 400 FM-15 0 15.0 N 90 2.0 0.0
2012-08-08 05:00:00 20120808 500 FM-15 10 15.0 N 80 0.0 2.0
1995-11-07 04:00:00 19951107 400 FM-15 110 15.0 N 340 5.0 2.0
1995-03-09 15:00:00 19950309 1500 FM-15 110 15.0 N 340 4.0 3.0
1994-10-20 08:00:00 19941020 800 FM-15 140 15.0 N 310 6.0 8.0
2013-03-09 17:00:00 20130309 1700 FM-15 80 14.0 N 10 8.0 2.0
2005-08-06 03:00:00 20050806 300 FM-15 350 14.0 N 100 4.0 1.0

1.4.2 Direction re-aligment

For some dataset, the 16 sectors are not record properly,

e.g. the sectors are [0,20,50 ...], need to redistribute the angle into 22.5, e.g. [0, 22.5, 45...]

In [17]:
display(df['dir'].value_counts().sort_index())
effective_column = df.query('dir < 999')['dir'].value_counts()[df['dir'].value_counts() > 30].sort_index()
if integer_data:
    SECTOR_LENGTH = 360/len(effective_column) 
else: 
    SECTOR_LENGTH = 10
print(len(effective_column), SECTOR_LENGTH)
0       5114
10      3736
20      3931
30      4370
40      4484
50      6036
60      6681
70      5524
80      5811
90      8968
100     8340
110     7085
120     7931
130     6770
140     4428
150     3796
160     3319
170     2573
180     2191
190     1555
200     1578
210     1991
220     1885
230     1882
240     2132
250     2360
260     3096
270     4399
280     4881
290     7184
300    11033
310     9313
320     9832
330    10032
340     7915
350     6258
999    25824
Name: dir, dtype: int64
36 10.0
In [18]:
df=realign_direction(df, effective_column)

1.4.3 0 Speed

In [19]:
with_too_many_zero, null_wind_frequency = is_with_too_many_zero(df['2005':])
delete_zero = with_too_many_zero
if delete_zero:
    df = df.query('(speed > 0)')
print(delete_zero, null_wind_frequency)
False 0.0412621359223
In [20]:
print(df.query('dir == 999')['speed'].value_counts())
df=fill_direction_999(df, SECTOR_LENGTH)
0.0    15499
2.0     5486
1.0     4531
3.0      229
4.0       43
5.0       15
3.1        8
4.1        4
2.1        3
7.0        2
5.1        2
6.0        2
Name: speed, dtype: int64

1.5 Time Shift Comparison

In [21]:
DIR_REDISTRIBUTE = 'even'
if DIR_REDISTRIBUTE == 'even':
    DIR_BIN = arange(-5, 360, 10) 
elif DIR_REDISTRIBUTE == 'round_up':
    DIR_BIN = arange(0, 360+10, 10) 

# Comparison between mid_year, looking for: 
# 1. Odd Even Bias
# 2. Time Shift of Wind Speed Distribution
bins = arange(0, df.speed.max() + 1)
df[:str(MID_YEAR)]['speed'].plot(
    kind='hist', alpha=0.5,bins=bins, label='< %s' % MID_YEAR)

df[str(MID_YEAR+1):]['speed'].plot(
    kind='hist', alpha=0.5,bins=bins, label='> %s' % MID_YEAR)

plt.suptitle('Speed Comparison between year < %s, > %s ' % (MID_YEAR, MID_YEAR), fontsize = 14)
plt_configure(xlabel='Speed', ylabel='Frequency', legend=True, figsize=(8, 3))
In [22]:
df[:str(MID_YEAR)]['dir'].plot(
    kind='hist', alpha=0.5,bins=DIR_BIN, label='< %s' % MID_YEAR)

df[str(MID_YEAR+1):]['dir'].plot(
    kind='hist', alpha=0.5,bins=DIR_BIN, label='> %s' % MID_YEAR)

plt.suptitle('Dir Comparison between year < %s, and > %s ' % (MID_YEAR, MID_YEAR), fontsize = 14)
plt_configure(xlabel='Dir', ylabel='Frequency', legend={'loc':'best'}, figsize=(8, 3), tight='x')
In [23]:
display(df[df['dir'].isnull()])
df.dropna(subset=['dir'], inplace=True)
date HrMn type dir speed wind_type dir_windrose
time
In [24]:
# Inspect the time shift of speed and degree distribution, and odd-even bias
check_time_shift(df, speed_unit_text=speed_unit_text, dir_unit_text=dir_unit_text)
1979 - 1980
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\__init__.py:938: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
  warnings.warn(self.msg_depr % (key, alt_key))
1981 - 1985
1986 - 1990
1991 - 1995
1996 - 2000
2001 - 2005
2006 - 2010
2011 - 2015
In [25]:
df.resample('A').mean().plot(y='speed', figsize=(4,3))
plt.gca().set_ylim(bottom=0)
df.resample('M').mean().plot(y='speed', figsize=(20,4))
plt.gca().set_ylim(bottom=0)
Out[25]:
(0, 6.0)
In [26]:
%%time
for column in ['speed', 'dir']:
    if column == 'speed':
        bins = arange(0, df[column].max()+1, 1)
    else:
        bins = arange(0, 361, 10)
    den, _ = np.histogram(df[column], bins=bins, density=True)
    y_top=max(den)*1.2
    for year in arange(1980, 2016):
        end_year = year
        sub_df = df[str(year):str(end_year)]
        if len(sub_df) > 1000:
            plt.figure()
            df[column].hist(bins=bins, alpha=0.3, normed=True)
            sub_df[column].hist(bins=bins, alpha=0.5, figsize=(3,1.5), normed=True)
            plt.gca().set_ylim(top=y_top)
            plt_configure(title=str(year))
    align_figures()
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\pyplot.py:524: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).
  max_open_warning, RuntimeWarning)
Wall time: 15.8 s
In [27]:
for column in ['speed', 'dir']:
    if column == 'speed':
        bins = arange(0, df[column].max()+1, 1)
    else:
        bins = arange(0, 361, 10)
    density_all, _ = np.histogram(df[column], bins=bins, density=True)
    df[column].hist(bins=bins, figsize=(5,3))

    R_squares = []
    years = []
    for year in arange(1980, 2016):
        start_year, end_year = year-1, year+1
        sub_df = df[str(start_year):str(end_year)]
        if len(sub_df) > 1000:
            density, _ = np.histogram(sub_df[column], bins=bins, density=True)
            y_mean = np.mean(density_all)
            SS_tot = np.sum(np.power(density_all - y_mean, 2))
            SS_res = np.sum(np.power(density_all - density, 2))

            R_square = 1 - SS_res / SS_tot
            R_squares.append(R_square)
            years.append(year)

    plt.figure()
    plot(years, R_squares)
    ylim = max(min(plt.gca().get_ylim()[0],0.85),0)
    plt.gca().set_ylim(bottom=ylim, top=1)
    plt_configure(figsize=(5,3))
    align_figures()

1.6 Re-distribute Direction and Speed (Optional)

e.g. Dir 50 -> -45 ~ 55, to make KDE result better

In [28]:
if integer_data:
    df = randomize_angle(df, DIR_REDISTRIBUTE, SECTOR_LENGTH)
In [29]:
if integer_data:
    if delete_zero:
        redistribute_method = 'down'
    else:
        redistribute_method = 'up'

    df, speed_redistribution_info = randomize_speed(df, redistribute_method)
Redistribute upward, e.g. 0 -> [0,1]

1.7 Generate (x,y) from (speed,dir)

In [30]:
# Cook orientation
# df['dir']= (df['dir'] + 180)%360
In [31]:
# There might be a small dot in the centre, which is due to too many zero (more than 1 speed) in center
# Scatter plot in matplot has performance issue, the speed is very slow
df['x'] = df['speed'] * cos(df['dir'] * pi / 180.0)
df['y'] = df['speed'] * sin(df['dir'] * pi / 180.0)

2. Re-select Data and Overview

2.1 Data Overview

In [32]:
## Summery of the data selection
print('Knot unit?', knot_unit)
print('Report type used:', report_type_most_used)
print('Sampling time used:', sample_times)
if 'speed_redistribution_info' in globals():
    print('Speed redistribution info:', speed_redistribution_info )

df_all_years = df # for later across-year comparison
if 'ECMWF' in file_path:
    df = df_all_years['2006':'2015']
else:
    df = df_all_years['2011':'2015']
# df = df.query('(HrMn == 0) and (speed >= 0.5) and (date%10000 > 900) and (date%10000 < 1000)' )
df.describe()
Knot unit? False
Report type used: FM-15
Sampling time used: [0, 30]
Speed redistribution info: Redistribute upward, e.g. 0 -> [0,1]
Out[32]:
date HrMn dir speed dir_windrose x y
count 3.635200e+04 36352.000000 36352.000000 36352.000000 36352.000000 36352.000000 36352.000000
mean 2.012661e+07 1149.460827 181.181139 4.541139 206.211653 1.004894 0.486100
std 1.194965e+04 692.188887 113.931639 1.959454 230.381866 3.032554 3.744255
min 2.011010e+07 0.000000 -4.989648 0.000081 0.000000 -11.755843 -11.118297
25% 2.012012e+07 500.000000 82.673834 3.179294 70.000000 -0.987732 -2.379252
50% 2.013013e+07 1100.000000 158.808463 4.402047 140.000000 1.362777 0.272945
75% 2.014021e+07 1700.000000 300.686454 5.751707 280.000000 3.288693 3.446902
max 2.015030e+07 2300.000000 354.995165 15.436942 999.000000 15.428750 14.599154
In [33]:
df.plot(y='speed',legend=True,figsize=(20,5))
Out[33]:
<matplotlib.axes._subplots.AxesSubplot at 0x1c21d828>
In [34]:
# Accumulation by month
df.resample('M').count().plot(y='date', kind='bar',figsize=(20,4))
Out[34]:
<matplotlib.axes._subplots.AxesSubplot at 0x1c278550>
In [35]:
# 90 degree is east
ax = WindroseAxes.from_ax()
viridis = plt.get_cmap('viridis')
ax.bar(df.dir_windrose, df.speed, normed=True, opening=0.8, edgecolor='white', nsector=36, cmap=viridis)
ax.set_legend()
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\cbook.py:136: MatplotlibDeprecationWarning: The axisbg attribute was deprecated in version 2.0. Use facecolor instead.
  warnings.warn(message, mplDeprecation, stacklevel=1)
In [36]:
if len(df) > 1000000:
    bins=arange(0,362)
    df['dir'].hist(bins=bins, normed=True,alpha=0.5,label='min')
    
    df = df_all_years.sample(n=500000, replace=True)    
    df['dir'].hist(bins=bins, normed=True,alpha=0.5,label='min resmapled')
    plt_configure(legend=True, figsize=(20,4))
In [37]:
x, y_weibull, y_cdf_weibull, weibull_params, y_ecdf = fit_weibull_and_ecdf(df.speed)

# 1. Histogram comparison
fig = plt.figure()
df['speed'].hist(bins=arange(0, df.speed.max()), alpha=0.5, label='Data', normed=True)             
plot(x, y_weibull, '-', color='black',label='Weibull')   
plt_configure(figsize=(4,3),xlabel='V',ylabel='PDF', legend=True)

# 2. CDF comparison
fig = plt.figure()
plot(log(x), log(-log(1-y_ecdf)),'o', label='ECDF')
plot(log(x), log(-log(1-y_cdf_weibull)),'-', label='Weibull')
plt_configure(xlabel="ln(V)", ylabel="ln(-ln(1-P)",legend={'loc':'best'}, figsize=(4,3))
align_figures()
D:\ProgramData\Anaconda3\lib\site-packages\ipykernel\__main__.py:11: RuntimeWarning: divide by zero encountered in log
D:\ProgramData\Anaconda3\lib\site-packages\ipykernel\__main__.py:12: RuntimeWarning: divide by zero encountered in log
In [38]:
df.plot(kind='scatter', x='x', y='y', alpha=0.05, s=2)
plt.gca().set_aspect('equal')
plt_configure(figsize=(3.2,3.2),xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text)

2.2 Overview by Direction

In [39]:
if len(effective_column) == 16:
    rebinned_angle = 22.5
else: 
    rebinned_angle = 10
In [40]:
%%time
original_incre, incre = SECTOR_LENGTH, rebinned_angle
start, end = -original_incre/2 + incre/2, 360

max_speed = df.speed.max()
max_count = max_count_for_angles(df, start, end, incre)
plot_range = [0, max_speed, 0, max_count*1.05]

for angle in arange(start, end, incre):
    start_angle, end_angle = angle-incre/2, angle+incre/2
    sub_df, sub_max_speed = select_df_by_angle(df, start_angle, end_angle)   
    
    fig = plt.figure()
    sub_df['speed'].hist(bins=arange(0, max_speed), alpha=0.5, label='Data')
    title ='%s (%s - %s), %s' % (angle, start_angle, end_angle, len(sub_df)) 
    plt.axis(plot_range)
    plt_configure(figsize=(3,1.5), title=title)
align_figures()
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\pyplot.py:524: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).
  max_open_warning, RuntimeWarning)
Wall time: 5.83 s

2.3 Overview by Month

In [41]:
%%time
current_df = df.query('speed>=1')
for month in arange(1, 13): 
    sub_df = current_df[current_df.index.month == month]
    ax = WindroseAxes.from_ax()
    ax.bar(sub_df.dir_windrose, sub_df.speed, normed=True, opening=0.8, edgecolor='white', nsector=36, cmap=plt.get_cmap('viridis'))
    plt_configure(figsize=(3,3), title='Month: %s'%(month))
align_figures()
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\cbook.py:136: MatplotlibDeprecationWarning: The axisbg attribute was deprecated in version 2.0. Use facecolor instead.
  warnings.warn(message, mplDeprecation, stacklevel=1)
Wall time: 17.9 s
In [42]:
df.describe()
Out[42]:
date HrMn dir speed dir_windrose x y
count 3.635200e+04 36352.000000 36352.000000 36352.000000 36352.000000 36352.000000 36352.000000
mean 2.012661e+07 1149.460827 181.181139 4.541139 206.211653 1.004894 0.486100
std 1.194965e+04 692.188887 113.931639 1.959454 230.381866 3.032554 3.744255
min 2.011010e+07 0.000000 -4.989648 0.000081 0.000000 -11.755843 -11.118297
25% 2.012012e+07 500.000000 82.673834 3.179294 70.000000 -0.987732 -2.379252
50% 2.013013e+07 1100.000000 158.808463 4.402047 140.000000 1.362777 0.272945
75% 2.014021e+07 1700.000000 300.686454 5.751707 280.000000 3.288693 3.446902
max 2.015030e+07 2300.000000 354.995165 15.436942 999.000000 15.428750 14.599154

3. Create input data and configuration

In [43]:
SPEED_SET = array(list(zip(df.x, df.y)))
if 'NUMBER_OF_GAUSSIAN' not in globals():
    NUMBER_OF_GAUSSIAN = 3
FIT_METHOD = 'square_error'
DEFAULT_BANDWDITH = 1.5 if knot_unit else 0.7
fig_list = []
In [44]:
fit_limit = ceil(df['speed'].quantile(.95))
fitting_axis_range = arange(-fit_limit, fit_limit+1, 1)
print(fitting_axis_range)

FITTING_RANGE = []
for i in fitting_axis_range:
    for j in fitting_axis_range:
        FITTING_RANGE.append([i,j])
        
plot_limit = ceil(df['speed'].quantile(.95))
PLOT_AXIS_RANGE = arange(-plot_limit, plot_limit+1, 1)
[-8 -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7  8]

4. Kernel Density Estimation

In [45]:
sample = SPEED_SET
KDE_KERNEL = 'gaussian'
# KDE_KERNEL, bandwidth = 'tophat', 1
In [46]:
%%time
if 'bandwidth' not in globals():
    bandwidth = DEFAULT_BANDWDITH
    from sklearn.grid_search import GridSearchCV
    # from sklearn.model_selection import GridSearchCV  ## too slow

    # The bandwidth value sometimes would be too radical
    if knot_unit:
        bandwidth_range = arange(0.7,2,0.2)
    else:
        bandwidth_range = arange(0.4,1.1,0.1)

    # Grid search is unable to deal with too many data (a long time is needed)
    if len(sample) > 50000:    
        df_resample=df.sample(n=50000, replace=True)
        bandwidth_search_sample = array(list(zip(df_resample.x, df_resample.y)))
    else:
        bandwidth_search_sample = sample

    grid = GridSearchCV(neighbors.KernelDensity(kernel = KDE_KERNEL),
                    {'bandwidth': bandwidth_range}, n_jobs=-1, cv=4) 

    grid.fit(bandwidth_search_sample)
    bandwidth = grid.best_params_['bandwidth']
    
print(bandwidth)
0.6
Wall time: 0 ns
In [47]:
if 'bandwidth' not in globals():
    bandwidth = DEFAULT_BANDWDITH
    
points = FITTING_RANGE    
config = {'bandwidth': bandwidth, 
          'fitting_range': FITTING_RANGE,
          'fit_limit': fit_limit,
          'kde_kernel': KDE_KERNEL}
In [48]:
# very slow if the dataset is too large, e.g. 100,000
# kde returns log prob, need to convert it
kde_result, kde = fit_kde(df, config)
print('bandwidth:', bandwidth, len(kde_result))
print(kde_result[:5])
bandwidth: 0.6 289
[  3.30793839e-08   3.56009766e-07   2.92983794e-06   1.16700501e-05
   2.24654326e-05]
In [49]:
# Plot jPDF
X = Y = PLOT_AXIS_RANGE
# Can't work if pass as generate_Z_from_X_Y(X,Y, exp(kde.score_samples())), need to use lambda
# see http://stackoverflow.com/questions/21035437/passing-a-function-as-an-argument-in-python
kde_Z = generate_Z_from_X_Y(X,Y, lambda coords: exp(kde.score_samples(coords)))
colorbar_lim = 0, kde_Z.max()

plot_3d_prob_density(X,Y,kde_Z)

fig_kde,ax1 = plt.subplots(figsize=(3.5,2.5))
plot_2d_prob_density(X,Y,kde_Z,xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text, ax=ax1)

with sns.axes_style({'axes.grid' : False}):
    from matplotlib import ticker
    fig_hist,ax2 = plt.subplots(figsize=(3.5,2.5))
    _,_,_,image = ax2.hist2d(df.x, df.y, bins=PLOT_AXIS_RANGE, cmap='viridis',)
    ax2.set_aspect('equal')
    cb = plt.colorbar(image)
    tick_locator = ticker.MaxNLocator(nbins=6)
    cb.locator = tick_locator
    cb.update_ticks()
    plt_configure(ax=ax2, xlabel='x'+speed_unit_text,ylabel='y'+speed_unit_text)
align_figures()

4.1 Bootstrap GOF limit

In [50]:
%%time
gof_kde=Parallel(n_jobs=-1)(delayed(resampled_kde)(df, kde_result, config) 
                                       for i in arange(20)) 
Wall time: 8.21 s
In [51]:
for gof_name in [ 'R_square', 'K_S','Chi_square']:
    plt.figure(figsize=(4,3))
    pd.DataFrame(gof_kde)[gof_name].hist()
    plt_configure(title=gof_name)
align_figures()

4.2 Bivariate Empirical Limit

In [52]:
%%time
gofs_mean_set_bivar = []
fig1, ax1 = plt.subplots(figsize=(3,2.5))
fig2, ax2 = plt.subplots(figsize=(3,2.5))
gofs_bivar_set={}

for year_length in [5, 10]:
    start_year, end_year = df_all_years.index.year[0], 2015-year_length+1
    df_standard = df_all_years[str(2015-year_length+1):'2015']
    kde_result_standard, _ = fit_kde(df_standard, config)
    gofs_bivar=Parallel(n_jobs=-1)(delayed(kde_gofs)(df_all_years[str(start_year):str(start_year+year_length-1)], kde_result_standard, config) 
                                   for start_year in arange(start_year, end_year+1)) 
    gofs_bivar_set[year_length] = gofs_bivar = pd.DataFrame(gofs_bivar, index=arange(start_year, end_year+1))
    if len(gofs_bivar)>0:
        gofs_bivar.plot(y='R_square', ax=ax1, label=year_length)
        gofs_bivar.plot(y='K_S', ax=ax2, label=year_length)
        year_lim = end_year-year_length-5, end_year-year_length
        gofs_mean = gofs_bivar.query('index >= @year_lim[0] & index <= @year_lim[1]').mean().to_dict()
        gofs_mean['year_lim']=year_lim
        gofs_mean_set_bivar.append(gofs_mean)
    
plt_configure(ax=ax1, ylabel='$\ R^2$', xlabel='start year')
plt_configure(ax=ax2, ylabel='K-S', xlabel='start year')
align_figures()
display(pd.DataFrame(gofs_mean_set_bivar).set_index('year_lim'))
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
year_lim
(2001, 2006) 1.791190 0.095563 0.000003 0.108623 0.522215 0.767865
(1991, 1996) 0.062636 0.053498 0.000002 0.073280 0.400354 0.878026
Wall time: 26.2 s

4.3 Univariate GOF Limit

In [53]:
def yearly_gof(df_all_years, start_year, end_year, density, y_ecdf, x, density_dir):
    df_previous = df_all_years[str(start_year):str(end_year)]
    _, _, density_expected, y_ecdf_previous, density_dir_expected = empirical_marginal_distribution(df_previous, x)
    
    # 1. Speed
    r_square = sector_r_square(density, density_expected)
    k_s = max(np.abs(y_ecdf - y_ecdf_previous))
    
    # 2. Direction
    r_square_dir = sector_r_square(density_dir, density_dir_expected)
    return {'year': start_year, 'r_square': r_square, 'k_s': k_s, 'r_square_dir': r_square_dir}
In [54]:
%%time
x = arange(0, df.speed.max() + 1)
fig1, ax1 = plt.subplots(figsize=(2.8,2.5))
fig2, ax2 = plt.subplots(figsize=(2.8,2.5))
fig3, ax3 = plt.subplots(figsize=(2.8,2.5))
gofs_mean_set = []
gofs_univar_set={}

for year_length in [5, 7, 10]:
    start_year, end_year =df_all_years.index.year[0], 2015-year_length+1
    df_standard = df_all_years[str(2015-year_length+1):str(2015)]
    _, _, density, y_ecdf, density_dir = empirical_marginal_distribution(df_standard, x)
    gofs = [yearly_gof(df_all_years, start_year, start_year+year_length-1, density, y_ecdf, x, density_dir) 
            for start_year in arange(start_year, end_year+1)]
    if len(gofs)>0:
        gofs = pd.DataFrame(gofs).set_index(['year'])  
        gofs_univar_set[year_length]=gofs
        ax1.plot(gofs.r_square, label=year_length)
        ax2.plot(gofs.k_s, label=year_length)
        ax3.plot(gofs.r_square_dir, label=year_length)
        year_lim = end_year-year_length-5, end_year-year_length
        gofs_mean = gofs.query('index >= @year_lim[0] & index <= @year_lim[1]').mean().to_dict()
        gofs_mean['year_lim']=year_lim
        gofs_mean_set.append(gofs_mean)
plt.tight_layout()


plt_configure(ax=ax1, ylabel='$\ R^2$', tight='xtight', legend=True)
plt_configure(ax=ax2, ylabel='K-S', tight='xtight', legend=True)
plt_configure(ax=ax3, ylabel='$\ R^2$', tight='xtight', legend=True)
align_figures()
display(pd.DataFrame(gofs_mean_set).set_index('year_lim'))
k_s r_square r_square_dir
year_lim
(2001, 2006) 0.111791 0.922759 0.816130
(1997, 2002) 0.087014 0.948546 0.849285
(1991, 1996) 0.054930 0.946491 0.809384
Wall time: 1.65 s

5. GMM by Expectation-maximization

In [55]:
sample=SPEED_SET
clf = mixture.GaussianMixture(n_components=NUMBER_OF_GAUSSIAN, covariance_type='full')
clf.fit(sample)
print(clf.converged_)
True
In [56]:
gmm_em_result = read_gmm_em_result(clf)
pretty_print_gmm(gmm_em_result)
Out[56]:
weight mean_x mean_y sig_x sig_y corr
1 0.422 2.820 -2.610 1.902 2.238 0.061
2 0.300 1.610 3.816 2.329 2.339 -0.231
3 0.277 -2.412 1.592 2.165 3.029 -0.119
In [57]:
fig,ax = plt.subplots(figsize=(3.5,3.5))
plot_gmm_ellipses(gmm_em_result, ax=ax, xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text)
GMM Plot Result
0.422174939622 [[ 2.81958737 -2.60982562]] [ 1.88992867  2.24859917] 169.754655418
0.300389686422 [[ 1.61034881  3.81599896]] [ 2.04591773  2.58979552] -135.544572335
0.277435373956 [[-2.41208339  1.59178169]] [ 2.13386129  3.05023916] -170.405868105
In [58]:
X = Y = PLOT_AXIS_RANGE
pdf_Z = generate_Z_from_X_Y(X,Y, lambda coords: exp(clf.score_samples(coords)))

def residule_between_kde_and_gmm(points):
    kde_vals = exp(kde.score_samples(points))
    gmm_vals = exp(clf.score_samples(points))
    return kde_vals - gmm_vals 

residual_Z = generate_Z_from_X_Y(X,Y, residule_between_kde_and_gmm)

plot_3d_prob_density(X,Y,pdf_Z)
plot_3d_prob_density(X,Y,residual_Z)
align_figures()

fig = plt.figure(figsize=(3.5,2.5))
plot_2d_prob_density(X,Y,kde_Z,xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text, colorbar_lim=colorbar_lim)
fig_em = plt.figure(figsize=(3.5,2.5))
plot_2d_prob_density(X,Y,pdf_Z,xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text, colorbar_lim=colorbar_lim)
fig = plt.figure(figsize=(3.5,2.5))
plot_2d_prob_density(X,Y,residual_Z,
                     xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text)
align_figures()

Goodness-of-fit Statistics

In [59]:
points = FITTING_RANGE
gmm_pdf_result = exp(clf.score_samples(points))
gof_df(gmm_pdf_result, kde_result)
Out[59]:
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.952 0.022 0.030 6.531626e-07 0.050 0.238
In [60]:
gmm_em = group_gmm_param_from_gmm_param_array(gmm_em_result, sort_group = True)
mixed_model_pdf_em = generate_gmm_pdf_from_grouped_gmm_param(gmm_em)

6. GMM by Optimization

In [61]:
sample = SPEED_SET
points = FITTING_RANGE
max_speed = df.speed.max()
print(FIT_METHOD)
square_error
In [62]:
# from GMM,EM 
# GMM format: weight, meanx, meany, sigx, sigy, rho
x0 = gmm_em_result

cons = [
        # sum of every 6th element, which is the fraction of each gaussian
        {'type': 'eq', 'fun': lambda x: sum(x[::6]) - 1},
        # # limit the width/height ratio of elliplse, optional
#         {'type': 'ineq', 'fun': lambda x: width_height_ratios_set(x) - 1/3},
#         {'type': 'ineq', 'fun': lambda x: 3 - width_height_ratios_set(x)},
]

bonds = [(0., 0.99),(-fit_limit, fit_limit),(-fit_limit, fit_limit),
         (0., fit_limit),(0., fit_limit),(-0.99, 0.99)]*(len(x0)//6)

result = sp.optimize.minimize(
    lambda x0: GMM_fit_score(x0, kde_result, points, FIT_METHOD),
    x0,
    bounds = bonds,
    constraints=cons,
    tol = 0.000000000001,
    options = {"maxiter": 500})
result
Out[62]:
     fun: -15.119397226394472
     jac: array([  2.54601061e+00,  -3.57627869e-07,  -3.57627869e-07,
        -3.57627869e-07,  -1.19209290e-07,  -3.57627869e-07,
         2.54601145e+00,   1.19209290e-07,   4.76837158e-07,
        -1.19209290e-07,   1.19209290e-07,  -7.15255737e-07,
         2.54601252e+00,  -2.38418579e-07,   1.19209290e-07,
         0.00000000e+00,   1.19209290e-07,  -1.19209290e-07,
         0.00000000e+00])
 message: 'Optimization terminated successfully.'
    nfev: 920
     nit: 45
    njev: 45
  status: 0
 success: True
       x: array([ 0.34526484,  3.38475543, -1.99379867,  1.64020943,  2.80463727,
        0.2295817 ,  0.23886243, -0.30923703, -1.89558117,  3.01790248,
        2.01781768, -0.50895595,  0.41587273, -0.14262158,  3.77940837,
        2.87739612,  2.02851059, -0.01191404])

6.1 GMM Result

In [63]:
gmm = group_gmm_param_from_gmm_param_array(result.x, sort_group = True)
mixed_model_pdf = generate_gmm_pdf_from_grouped_gmm_param(gmm)
gmm_pdf_result = mixed_model_pdf(points)
pretty_print_gmm(gmm)
Out[63]:
weight mean_x mean_y sig_x sig_y corr
1 0.416 -0.143 3.779 2.877 2.029 -0.012
2 0.345 3.385 -1.994 1.640 2.805 0.230
3 0.239 -0.309 -1.896 3.018 2.018 -0.509
In [64]:
fig_gmm, ax = plt.subplots(figsize=(3.5,3.5))
plot_gmm_ellipses(gmm, ax=ax, xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text)
GMM Plot Result
0.415872732939 [[-0.14262158  3.77940837]] [ 2.02822443  2.87759784] -90.9563765255
0.345264841224 [[ 3.38475543 -1.99379867]] [ 1.57577843  2.84133763] 168.899645623
0.238862425837 [[-0.30923703 -1.89558117]] [ 1.61132011  3.25314787] -115.453789528

6.2 Bivariate Goodness-of-fit statistics

In [65]:
gof_df(gmm_pdf_result, kde_result)
Out[65]:
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.980 0.014 0.043 2.714746e-07 0.032 0.153
In [66]:
# Empirical Power
pd.DataFrame(gofs_mean_set_bivar).set_index('year_lim')
Out[66]:
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
year_lim
(2001, 2006) 1.791190 0.095563 0.000003 0.108623 0.522215 0.767865
(1991, 1996) 0.062636 0.053498 0.000002 0.073280 0.400354 0.878026
In [67]:
%%time
# Solid is Empirical, Dash is against previous data
fig1, ax1 = plt.subplots(figsize=(3,2.5))
fig2, ax2 = plt.subplots(figsize=(3,2.5))
gofs_mean_set_bivar_previous = []
prop_cycle = iter(mpl.rcParams['axes.color_cycle'])
for year_length in [10]:
    color = next(prop_cycle)
    start_year, end_year = df_all_years.index.year[0], 2015-year_length+1
    gofs_bivar_previous=Parallel(n_jobs=-1)(delayed(gmm_gofs_in_previous)(df_all_years[str(sub_start_year):str(sub_start_year+year_length-1)], gmm_pdf_result, config) 
       for sub_start_year in arange(start_year, end_year+1)) 
    gofs_bivar_previous=pd.DataFrame(gofs_bivar_previous, index=arange(start_year, end_year+1))    
    
    gofs_bivar_set[year_length].plot(y='R_square',ax=ax1, style='--', color=color, label='')
    gofs_bivar_set[year_length].plot(y='K_S',ax=ax2, style='--', color=color, label='')
    gofs_bivar_previous.plot(y='R_square', color=color, ax=ax1, label=year_length)
    gofs_bivar_previous.plot(y='K_S', color=color, ax=ax2, label=year_length)
    year_lim = end_year-year_length-5, end_year-year_length
    gofs_mean = gofs_bivar_previous.query('index >= @year_lim[0] & index <= @year_lim[1]').mean().to_dict()
    gofs_mean['year_lim']=year_lim
    gofs_mean_set_bivar_previous.append(gofs_mean)
    
plt_configure(ax=ax1, ylabel='$\ R^2$', xlabel='start year', legend=True)
plt_configure(ax=ax2, ylabel='K-S', xlabel='start year', legend=True)
align_figures()
display(pd.DataFrame(gofs_mean_set_bivar_previous).set_index('year_lim'))
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\__init__.py:938: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
  warnings.warn(self.msg_depr % (key, alt_key))
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
year_lim
(1991, 1996) 0.23851 0.089415 0.000004 0.066343 0.579633 0.78654
Wall time: 14.6 s
In [68]:
X = Y = PLOT_AXIS_RANGE
pdf_Z = generate_Z_from_X_Y(X,Y, mixed_model_pdf)# passing a function as an argument

def residule_between_kde_and_gmm(points):
    kde_vals = exp(kde.score_samples(points))
    gmm_vals = mixed_model_pdf(points)
    return kde_vals - gmm_vals 

residual_Z = generate_Z_from_X_Y(X,Y, residule_between_kde_and_gmm)

plot_3d_prob_density(X,Y,pdf_Z)
plot_3d_prob_density(X,Y,residual_Z)
align_figures()

fig = plt.figure(figsize=(3.5,2.5))
plot_2d_prob_density(X,Y,kde_Z, xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text)
fig_gmm = plt.figure(figsize=(3.5,2.5))
plot_2d_prob_density(X,Y,pdf_Z, xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text)
fig = plt.figure(figsize=(3.5,2.5))
plot_2d_prob_density(X,Y,residual_Z,  xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text)
align_figures()

6.3 Univariate Goodness-of-fit

In [69]:
def f(V,theta):
    return (mixed_model_pdf([[V*cos(theta),V*sin(theta)]]))*V

def f_em(V,theta):
    return (mixed_model_pdf_em([[V*cos(theta),V*sin(theta)]]))*V
In [70]:
%%time
x = arange(0, max_speed, 0.5)
# 1. Fit Weibull
_, y_weibull, y_cdf_weibull, weibull_params, y_ecdf = fit_weibull_and_ecdf(df.speed, x=x)

# 2. GMM Model
y_ =[integrate.nquad(f, [[x_-0.01, x_+0.01],[0, 2*pi]]) for x_ in x]
y_gmm = array(list(zip(*y_))[0])/0.02

# 3. Plot Comparison
df['speed'].hist(bins=arange(0, df.speed.max()), alpha=0.5, label='Data')
plot(x, y_gmm*len(df.speed),'-', color='black', label='GMM')
plot(x, y_weibull*len(df.speed), '--', color='black', label='Weibull') 
print('Speed Distribution Comparison')
plt_configure(xlabel='Speed'+speed_unit_text,
              ylabel='Frequency',legend=True, figsize=(4, 2))
plt.gca().set_ylim(bottom = 0)
plt.tight_layout()
plt.locator_params(axis='y', nbins=5)

# 4. R square for GMM, Weibull
print(R_square_for_speed(df['speed'], f, weibull_params, f_em))
Speed Distribution Comparison
(0.99084360184616516, 0.98101941242152169, 0.98500795631734472)
Wall time: 19.7 s
In [71]:
%%time
y_ = [integrate.nquad(f, [[0, x_val],[0, 2*pi]]) for x_val in x]
y_cdf_gmm = array(list(zip(*y_))[0])

# 5.2. CDF Comaprison
plot(x, y_ecdf,'o', alpha=0.8, label='Data')
plot(x, y_cdf_gmm,'-', color='black',label='GMM')
plot(x, y_cdf_weibull,'--', color='black',label='Weibull')
plt_configure(xlabel = "V", ylabel='P', legend=True, figsize=(4,3))

plt.figure()
plot(log(x), log(-log(1-y_ecdf)),'o', label = 'Empirical')
plot(log(x), log(-log(1-y_cdf_weibull)),'--', label = 'Weibull')
plot(log(x), log(-log(1-y_cdf_gmm)),'-', color='black', label = 'GMM')
plt_configure(xlabel='ln(V)',ylabel='ln(-ln(1-P))',legend={'loc':'best'}, figsize=(4,3))
align_figures()

cdf_diff, cdf_diff_weibull= np.abs(y_ecdf - y_cdf_gmm), np.abs(y_ecdf - y_cdf_weibull)
print(cdf_diff.max(), cdf_diff_weibull.max()) 
print(x[cdf_diff.argmax()], x[cdf_diff_weibull.argmax()])
D:\ProgramData\Anaconda3\lib\site-packages\ipykernel\__main__.py:11: RuntimeWarning: divide by zero encountered in log
D:\ProgramData\Anaconda3\lib\site-packages\ipykernel\__main__.py:12: RuntimeWarning: divide by zero encountered in log
D:\ProgramData\Anaconda3\lib\site-packages\ipykernel\__main__.py:13: RuntimeWarning: divide by zero encountered in log
0.0179336667415 0.0734776723628
2.0 5.0
Wall time: 9.37 s
In [72]:
# Calculate Angle Distribution
x = linspace(0,2*pi, num=36+1)
y_ =[integrate.nquad(f, [[0, inf],[x_-pi/36, x_+pi/36]]) for x_ in x]
y = array(list(zip(*y_))[0])
density, _ = dir_hist(df['dir'], bins=arange(-5, 375, 10), density=True)

plt.bar(arange(0, 360, 10), density*10*len(df['dir']), width=10, alpha=0.5, label='Data')
plot(x/pi*180, y*len(df['dir']) ,'-', color='black', label='GMM')
plt_configure(xlabel='Direction'+dir_unit_text, ylabel='Frequency', 
              legend={'loc': 'best'} ,tight='xtight',figsize = (4,2))
plt.tight_layout()
dir_fig = plt.gcf()
print('Direction Distribution Comparison')
sector_r_square(density*10, y[:-1])
Direction Distribution Comparison
Out[72]:
0.90690015560446557
In [73]:
pd.DataFrame(gofs_mean_set).set_index('year_lim')
Out[73]:
k_s r_square r_square_dir
year_lim
(2001, 2006) 0.111791 0.922759 0.816130
(1997, 2002) 0.087014 0.948546 0.849285
(1991, 1996) 0.054930 0.946491 0.809384
In [74]:
fig1, ax1 = plt.subplots(figsize=(2.8,2.5))
fig2, ax2 = plt.subplots(figsize=(2.8,2.5))
fig3, ax3 = plt.subplots(figsize=(2.8,2.5))
prop_cycle = iter(mpl.rcParams['axes.color_cycle'])
gofs_mean_set = []

x = bins = arange(0, df['speed'].max() + 1)
_, _, density_speed_expected_gmm, y_cdf_gmm, density_dir_expected = gmm_marginal_distribution(f, x)
_, _, density_expected_weibull, y_cdf_weibull = fit_weibull(df.speed, x, weibull_params)
    
for year_length in [10]:
    start_year, end_year = df_all_years.index.year[0], 2015-year_length+1
    gofs = []
    for sub_start_year in arange(start_year, end_year+1):
        df_previous = df_all_years[str(sub_start_year):str(sub_start_year+year_length-1)]
        
        _, _, density_speed, y_ecdf_previous, density_dir = empirical_marginal_distribution(df_previous, x) 

        r_square_speed = sector_r_square(density_speed, density_speed_expected_gmm)
        r_square_speed_weibull = sector_r_square(density_speed, density_expected_weibull)

        k_s_speed = (np.abs(y_ecdf_previous - y_cdf_gmm)).max()
        k_s_speed_weibull = (np.abs(y_ecdf_previous - y_cdf_weibull)).max()
        
        r_square_dir = sector_r_square(density_dir*10, density_dir_expected[:-1])
        gofs.append({'year': sub_start_year, 
                     'r_square': r_square_speed, 'k_s': k_s_speed, 'r_square_dir': r_square_dir,
                      'r_square_weibulll': r_square_speed_weibull, 'k_s_weibulll': k_s_speed_weibull})

    gofs=pd.DataFrame(gofs).set_index(['year'])  
    year_lim = end_year-year_length-5, end_year-year_length
    gofs_mean = gofs.query('index >= @year_lim[0] & index <= @year_lim[1]').mean().to_dict()
    gofs_mean['year_lim']=year_lim
    gofs_mean_set.append(gofs_mean)

    color = next(prop_cycle)
    # GMM agains previous data
    gofs.plot(y='r_square', ax=ax1, label=year_length, color=color)
    gofs.plot(y='k_s', ax=ax2, color=color, label=year_length)
    gofs.plot(y='r_square_dir', ax=ax3, label=year_length, color=color)
    # Empricial agains previous data
    ax1.plot(gofs_univar_set[year_length].r_square, label='', color=color, linestyle='--')
    ax2.plot(gofs_univar_set[year_length].k_s, label='', color=color, linestyle='--')
    ax3.plot(gofs_univar_set[year_length].r_square_dir, label='', color=color, linestyle='--')
    color = next(prop_cycle)
    gofs.plot(y='r_square_weibulll', ax=ax1, label='Weibull', color=color)
    gofs.plot(y='k_s_weibulll', ax=ax2, label='Weibull', color=color)
    
    plt_configure(ax=ax1, ylabel='$\ R^2$', xlabel='start year', legend=True)
    plt_configure(ax=ax2, ylabel='K-S', xlabel='start year', legend=True)
    plt_configure(ax=ax3, ylabel='$\ R^2$', xlabel='start year', legend=True)

align_figures()
display(pd.DataFrame(gofs_mean_set).set_index('year_lim'))
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\__init__.py:938: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
  warnings.warn(self.msg_depr % (key, alt_key))
k_s k_s_weibulll r_square r_square_dir r_square_weibulll
year_lim
(1991, 1996) 0.095916 0.152313 0.875738 0.764356 0.871552

6.4 Sectoral Comaprison

In [75]:
%%time
incre = max(SECTOR_LENGTH, 10)
density_collection=Parallel(n_jobs=-1)(delayed(direction_compare)(gmm, df, angle, incre) 
                                        for angle in arange(0, 360, incre))  
# This R square is computed as in paper 
# Comparison of bivariate distribution constructionapproaches for analysing wind speed anddirection data
# http://onlinelibrary.wiley.com/doi/10.1002/we.400/full
print(true_R_square(density_collection))
0.910794820155
Wall time: 8.38 s
In [76]:
# Turn to parrallel would run 50% faster
# Calculate Speed Distribution
def model_data_comparison(df, original_incre = 10, incre = 10):
    start, end = -original_incre/2 + incre/2, 360
    curve_collection = []
    max_speed = df.speed.max()
    
    # Find a max count for plotting histogram
    max_count = max_count_for_angles(df, start, end, incre)
    plot_range = [0, max_speed, 0, max_count*1.05]
    
    for angle in arange(start, end, incre):
        angle_radian, incre_radian = np.radians([angle, incre])  
        start_angle, end_angle = angle-incre/2, angle+incre/2
        
        # 0. Select data from observation
        sub_df, sub_max_speed = select_df_by_angle(df, start_angle, end_angle)
        data_size = len(sub_df.speed)
        # 1. Get Weibull and ECDF
        x, y_weibull, y_cdf_weibull, weibull_params, y_ecdf = fit_weibull_and_ecdf(sub_df.speed)
        # 2. Get GMM PDF, CDF
        _, y_gmm, y_cdf_gmm, direction_prob = gmm_integration_in_direction(f, angle_radian-incre_radian/2, angle_radian+incre_radian/2, x)
        
        # 3. R square for GMM, Weibull
        bins = arange(0, sub_df.speed.max()+1)
        density, _ = np.histogram(sub_df['speed'], bins=bins, normed=True)
        density_expected_gmm_ =[integrate.nquad(f, [[x_, x_+1],[angle_radian-incre_radian/2, angle_radian+incre_radian/2]]) 
                            for x_ in bins[:-1]]
        density_expected_gmm = array(list(zip(*density_expected_gmm_ ))[0])/direction_prob
        R_square_gmm = sector_r_square(density, density_expected_gmm)
        
        density_expected_weibull = sp.stats.weibull_min.cdf(bins[1:], *weibull_params) - sp.stats.weibull_min.cdf(bins[:-1], *weibull_params) 
        R_square_weibull = sector_r_square(density, density_expected_weibull)

        # 4. K-S for GMM, Weibull
        cdf_diff, cdf_diff_weibull= np.abs(y_ecdf - y_cdf_gmm), np.abs(y_ecdf - y_cdf_weibull)
                
        # 5. Make Plots
        fig = plt.figure(figsize=(10,1.9))
        # 5.1. Frequency Comparison
        ax1 = fig.add_subplot(1,3,1)        
        sub_df['speed'].hist(bins=arange(0, sub_max_speed), alpha=0.5, label='Data')                  
        plot(x, y_gmm*data_size,'-', color='black', label='GMM')
        plot(x, y_weibull*data_size, '--', color='black',label='Weibull')   
        plt_configure(xlabel = "V", ylabel='Frequency', legend=True)
        plt.axis(plot_range)
        
        # 5.2. CDF Comaprison
        ax2 = fig.add_subplot(1,3,2)
        plot(x, y_ecdf,'o', alpha=0.8, label='Data')
        plot(x, y_cdf_gmm,'-', color='black',label='GMM')
        plot(x, y_cdf_weibull,'--', color='black',label='Weibull')
        plt.gca().set_xlim(right = max_speed)
        plt_configure(xlabel = "V", ylabel='P', legend=True)
        
        curves = {'direction': angle, 'datasize': data_size, 'weight': direction_prob, 'x': x, 
                  'gmm_pdf': y_gmm, 'gmm_cdf': y_cdf_gmm,
                  'weibull_pdf': y_weibull, 'weibull_cdf': y_cdf_weibull, 'ecdf': y_ecdf,
                  'max_cdf_diff_gmm': cdf_diff.max(), 'max_cdf_diff_weibull': cdf_diff_weibull.max(), 
                  'r_square_gmm': R_square_gmm, 'r_square_weibull': R_square_weibull}
        curve_collection.append(curves)
        
        plt.tight_layout()
        plt.show()
        print('%s (%s - %s) degree' % (angle, start_angle, end_angle))
        print('data size:', len(sub_df), 'weight', len(sub_df)/len(df))
        print('GMM', 'Weibull')
        print('R square', R_square_gmm,  R_square_weibull)
        print('max diff:', cdf_diff.max(), cdf_diff_weibull.max(), 
              'speed value:', x[cdf_diff.argmax()], x[cdf_diff_weibull.argmax()], 'y gmm', y_cdf_gmm[cdf_diff.argmax()])
        print(' ')
    return curve_collection
In [77]:
%%time
if len(effective_column) == 16:
    rebinned_angle = 22.5
else: 
    rebinned_angle = 20
    
curve_collection = model_data_comparison(df, SECTOR_LENGTH, rebinned_angle)
5.0 (-5.0 - 15.0) degree
data size: 1179 weight 0.03243287852112676
GMM Weibull
R square 0.961803211421 0.949052583843
max diff: 0.0386956090745 0.0432041891926 speed value: 2.38776126762 5.57144295778 y gmm 0.137932250296
 
25.0 (15.0 - 35.0) degree
data size: 1869 weight 0.051413952464788734
GMM Weibull
R square 0.879183585504 0.941030624583
max diff: 0.0889436623613 0.0480386871456 speed value: 4.76738078864 2.04316319513 y gmm 0.574512731432
 
45.0 (35.0 - 55.0) degree
data size: 2275 weight 0.0625825264084507
GMM Weibull
R square 0.95310081219 0.974132109696
max diff: 0.0365571748387 0.0934947143733 speed value: 5.78723154388 5.78723154388 y gmm 0.703223044941
 
65.0 (55.0 - 75.0) degree
data size: 2182 weight 0.060024207746478875
GMM Weibull
R square 0.981056396234 0.976704804408
max diff: 0.0595297270356 0.0521892949011 speed value: 5.41038531511 6.0866834795 y gmm 0.638814786614
 
85.0 (75.0 - 95.0) degree
data size: 3411 weight 0.0938325264084507
GMM Weibull
R square 0.960371824111 0.965590048825
max diff: 0.0622776633351 0.0330622617524 speed value: 7.72677723991 5.40874406794 y gmm 0.943250984942
 
105.0 (95.0 - 115.0) degree
data size: 2718 weight 0.07476892605633803
GMM Weibull
R square 0.903659025962 0.960534004375
max diff: 0.0872941862033 0.0653643728591 speed value: 4.18621788458 4.18621788458 y gmm 0.378857395842
 
125.0 (115.0 - 135.0) degree
data size: 2549 weight 0.07011993838028169
GMM Weibull
R square 0.953177576552 0.942360524119
max diff: 0.0686214836367 0.137386580615 speed value: 3.05850011594 6.11700023189 y gmm 0.187883939502
 
145.0 (135.0 - 155.0) degree
data size: 1271 weight 0.03496368838028169
GMM Weibull
R square 0.945650405206 0.951946510832
max diff: 0.0383480338597 0.137230847523 speed value: 6.42847474437 4.99992480118 y gmm 0.786577774222
 
165.0 (155.0 - 175.0) degree
data size: 1248 weight 0.03433098591549296
GMM Weibull
R square 0.945564360775 0.947417173746
max diff: 0.0434773131708 0.0915680802425 speed value: 4.26792675333 4.26792675333 y gmm 0.523029097086
 
185.0 (175.0 - 195.0) degree
data size: 929 weight 0.02555567781690141
GMM Weibull
R square 0.913615655924 0.944280205685
max diff: 0.0954255446908 0.0740645872989 speed value: 3.72435783859 3.72435783859 y gmm 0.501991032274
 
205.0 (195.0 - 215.0) degree
data size: 889 weight 0.02445532570422535
GMM Weibull
R square 0.957189847019 0.951027622377
max diff: 0.0267695986822 0.0757843292655 speed value: 4.01387007908 4.01387007908 y gmm 0.67739238107
 
225.0 (215.0 - 235.0) degree
data size: 882 weight 0.024262764084507043
GMM Weibull
R square 0.915349334059 0.964093443994
max diff: 0.0679380980716 0.070153056672 speed value: 4.80564494541 2.88338696724 y gmm 0.89220113662
 
245.0 (235.0 - 255.0) degree
data size: 737 weight 0.02027398767605634
GMM Weibull
R square 0.857539024274 0.990683112586
max diff: 0.0821528169603 0.0212542071739 speed value: 1.86030301697 3.72060603395 y gmm 0.214997793623
 
265.0 (255.0 - 275.0) degree
data size: 1228 weight 0.03378080985915493
GMM Weibull
R square 0.922279725067 0.984898143083
max diff: 0.0677723136701 0.0789954993847 speed value: 4.45835079246 3.34376309435 y gmm 0.715980782725
 
285.0 (275.0 - 295.0) degree
data size: 2167 weight 0.05961157570422535
GMM Weibull
R square 0.941949622977 0.956983619601
max diff: 0.0563993639896 0.0864881614286 speed value: 3.61157744453 3.61157744453 y gmm 0.315081946578
 
305.0 (295.0 - 315.0) degree
data size: 4149 weight 0.11413402288732394
GMM Weibull
R square 0.991544198677 0.990164930718
max diff: 0.0122156782579 0.0754529572724 speed value: 3.39760333238 6.11568599828 y gmm 0.217237201954
 
325.0 (315.0 - 335.0) degree
data size: 3596 weight 0.09892165492957747
GMM Weibull
R square 0.958768320026 0.968013536519
max diff: 0.0466848209421 0.0351774278877 speed value: 5.04539160511 5.04539160511 y gmm 0.599032642907
 
345.0 (335.0 - 355.0) degree
data size: 2586 weight 0.07113776408450705
GMM Weibull
R square 0.962003822319 0.959113286822
max diff: 0.0602091467475 0.0925006815725 speed value: 2.91193972039 3.63992465049 y gmm 0.201740469253
 
Wall time: 44.6 s
In [78]:
diff_df = pd.DataFrame(curve_collection) 

gmm_mean, weibull_mean = plot_sectoral_comparison(diff_df.r_square_gmm, diff_df.r_square_weibull, 
                                                  diff_df.direction, diff_df.datasize)
plt_configure(ylabel="$\ R^2$", xlabel='Direction'+dir_unit_text)
ylim = min(plt.gca().get_ylim()[0],0.75)
plt.gca().set_ylim(top=1, bottom=ylim)
plt.tight_layout()
print(gmm_mean, weibull_mean)
0.9477743688075736 0.9641605037757652
In [79]:
gmm_mean, weibull_mean = plot_sectoral_comparison(diff_df.max_cdf_diff_gmm, diff_df.max_cdf_diff_weibull, 
                                                  diff_df.direction, diff_df.datasize)
plt_configure(ylabel="K-S", xlabel='Direction'+dir_unit_text)
ylim = max(plt.gca().get_ylim()[1],0.25)
plt.gca().set_ylim(top=ylim, bottom=0)
plt.tight_layout()
print(gmm_mean, weibull_mean)
0.05479299726997704 0.07175614433598361
In [80]:
# Compare direction weight with previous figure
display(dir_fig)

6.5 Insufficient-fit Sector Investigation

(1) Data Variability, by Bootstrap (Resampling)

In [81]:
angle =  max_diff_angle = diff_df.ix[diff_df['max_cdf_diff_gmm'].idxmax()]['direction']
incre = rebinned_angle
In [82]:
FRACTION = 1

# Select data from observation
start_angle, end_angle = angle-incre/2, angle+incre/2
angle_radian, incre_radian = radians(angle), radians(incre)  
sub_df, sub_max_speed = select_df_by_angle(df, start_angle, end_angle)
In [83]:
x = arange(0, sub_max_speed, 0.5)
_, y_weibull, y_cdf_weibull, weibull_params, y_ecdf = fit_weibull_and_ecdf(sub_df.speed, x)
_, y_gmm, y_cdf_gmm, direction_prob = gmm_integration_in_direction(f, angle_radian-incre_radian/2, angle_radian+incre_radian/2, x)

fig = plt.figure(figsize=(10,1.9))
ax1 = fig.add_subplot(1,3,1)   
ax2 = fig.add_subplot(1,3,2)   

# 1. Data
bins=arange(0, sub_max_speed)
sub_df['speed'].hist(ax=ax1, bins=bins, alpha=0.5, label='Data', normed=True)  

# 2. GMM
ax1.plot(x, y_gmm,'-', color='black', label='GMM')
ax2.plot(x, y_cdf_gmm,'-', color = 'black', label='GMM')

# 3. Weilbull 
ax1.plot(x, y_weibull,'--',color='black',label='Weibull')
ax2.plot(x, y_cdf_weibull,'--',label='Weibull')

# 4. Data Resampled
count_collection = []
for i in range(1,100):
    sub_df_resampled = sub_df.sample(frac=FRACTION, replace=True)    
    resampled_count, _ = np.histogram(sub_df_resampled['speed'], bins=bins, normed=True) 
    count_collection.append(resampled_count)
    
    ecdf = sm.distributions.ECDF(sub_df_resampled.speed)
    y_ecdf = ecdf(x) 
    ax2.plot(x, y_ecdf,':', label='Data Resampled')
    if i == 1: 
        plt_configure(ax=ax2, xlabel = "V", ylabel='P', legend={'loc':'best'})

print('%s (%s - %s) Degree Speed Distribution' % (angle, start_angle, end_angle))
count_collection = np.array(count_collection)
mx, mn = np.max(count_collection,0), np.min(count_collection,0)
ax1.plot(bins[1:]-0.5, mx, ':', color='blue')
ax1.plot(bins[1:]-0.5, mn, ':', color='blue', label='Resample limit')
ax1.set_ylim(bottom = 0)
# plt_configure(ax=ax1, xlabel='$V$',ylabel='Frequency',legend={'loc':'best'})
plt_configure(ax=ax1, xlabel='V', ylabel='Frequency',legend={'loc':'best'})
ax1.locator_params(axis='y', nbins=5)
ax2.locator_params(axis='y', nbins=5)
plt.tight_layout()
diff = abs(y_ecdf - y_cdf_gmm)
print(diff.max(), x[diff.argmax()], y_cdf_gmm[diff.argmax()])
185.0 (175.0 - 195.0) Degree Speed Distribution
0.081442893526 4.0 0.557954307766

(2) Time Variability

In [84]:
fig_time_variability_3d = plt.figure()
ax1 = fig_time_variability_3d.gca(projection='3d')

fig_time_variability_cdf,ax2 = plt.subplots(figsize=(3,1.8))
fig_time_variability_weibull, ax3 = plt.subplots(figsize=(3,1.8))

ax2.plot(x, y_cdf_gmm,'-', color='black', label = 'GMM')
ax2.plot(x, y_cdf_weibull,'--', label='Weibull')

# 3. Data
prop_cycle=iter(mpl.rcParams['axes.color_cycle'])
for start_time in range(2001, 2015, 5):
    end_time = start_time + 4 
    df_other_years = df_all_years[str(start_time):str(end_time)]
    df_other_years_at_angle, sub_max_speed_other_year = select_df_by_angle(df_other_years, start_angle, end_angle)
    if len(df_other_years_at_angle) > 0 :
        
        ecdf = sm.distributions.ECDF(df_other_years_at_angle.speed)
        y_ecdf = ecdf(x)
        ax2.plot(x, y_ecdf,':', label = start_time)
        
        count, division = np.histogram(df_other_years_at_angle['speed'], normed=True,
                                       bins=arange(0, sub_max_speed_other_year))
        ax1.bar(left=division[:-1], height=count, zs=start_time, zdir='x', 
                color=next(prop_cycle), alpha=0.8)
        x_3d = start_time*np.ones_like(x)
        ax1.plot(x_3d, x, y_gmm, '-', color='black', label='GMM'  if start_time == 2011 else '')
        ax1.plot(x_3d, x, y_weibull, '--', color='blue', label='Weibull' if start_time == 2011 else '')
        
print('%s (%s - %s) Degree Speed Distribution' % (angle, start_angle, end_angle))
ax1.set_ylim(bottom = 0)
ax1.set_zlabel('Frequency')
plt_configure(ax=ax1, xlabel='Time',ylabel='V', legend=True)
plt_configure(ax=ax2, xlabel = "V", ylabel='P', legend={'loc':'best'})

ax1.set_zlim(bottom = 0)
align_figures()
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\__init__.py:938: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
  warnings.warn(self.msg_depr % (key, alt_key))
185.0 (175.0 - 195.0) Degree Speed Distribution

(3) Adjacent Sector Variability

In [85]:
incre = rebinned_angle
angle_group = [max_diff_angle-incre, max_diff_angle, max_diff_angle+incre]
In [86]:
fig_adjecent_variability_3d = plt.figure()
ax1 = fig_adjecent_variability_3d.gca(projection='3d')
fig_adjecent_variability_cdf, ax2 = plt.subplots(figsize=(3,1.8))
fig_adjecent_variability_weibull, ax3 = plt.subplots(figsize=(3,1.8))

legend_3d = False
prop_cycle=iter(mpl.rcParams['axes.color_cycle'])

curve_df = pd.DataFrame(curve_collection)

for angle in angle_group:
    curves = curve_df.query('direction == @angle%360').T.to_dict()
    curves = curves[list(curves)[0]]
    data_size, x =  curves['datasize'], curves['x']
    y_gmm, y_cdf_gmm =  curves['gmm_pdf'], curves['gmm_cdf'] 
    y_weibull, y_cdf_weibull, y_cdf = curves['weibull_pdf'],  curves['weibull_cdf'], curves['ecdf']

    linestyle = '-' if angle == max_diff_angle else ':'
    alpha = 0.7 if angle == max_diff_angle else 0.3

    ax2.plot(x, y_gmm*data_size, linestyle, label=angle)        
    ax3.plot(x, y_weibull*data_size, linestyle, label=angle)

    start_angle, end_angle = angle-incre/2, angle+incre/2
    sub_df, sub_max_speed = select_df_by_angle(df, start_angle, end_angle)

    x_3d = angle*np.ones_like(x)
    ax1.plot(x_3d, x, y_gmm*data_size, color='black', label='GMM')
    ax1.plot(x_3d, x, y_weibull*data_size, color='blue', linestyle='--',label='Weibull')

    count, division = np.histogram(sub_df['speed'], bins=arange(0, sub_max_speed))
    ax1.bar(left=division[:-1], height=count, zs=angle, zdir='x', color=next(prop_cycle), alpha=0.8)

    if legend_3d == False:
        ax1.legend()
        legend_3d = True
        
plt_configure(ax=ax1, xlabel='Direction', ylabel='Speed')   
plt_configure(ax=ax2, xlabel='V',ylabel='Frequency',legend={'loc':'best'})
plt_configure(ax=ax3, xlabel='V',ylabel='Frequency',legend={'loc':'best'})
ax1.set_zlabel('Frequency')
ax1.set_zlim(bottom = 0)
ylim = max(ax1.get_ylim()[1],ax3.get_ylim()[1])
ax2.set_ylim(bottom = 0, top=ylim)
ax3.set_ylim(bottom = 0, top=ylim)

print(max_diff_angle) 
print('GMM, Weibull, Histogram')
align_figures()
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\__init__.py:938: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
  warnings.warn(self.msg_depr % (key, alt_key))
185.0
GMM, Weibull, Histogram

7. Result Variability & Cross-Validation

In [87]:
if 'bandwidth' not in globals():
    bandwidth = DEFAULT_BANDWDITH    
if 'FIT_METHOD' not in globals():
    FIT_METHOD = 'square_error'       
if 'KDE_KERNEL' not in globals():
    KDE_KERNEL = 'gaussian'
    
config = {'bandwidth': bandwidth, 
          'fitting_range': FITTING_RANGE,
          'fit_limit': fit_limit,
          'kde_kernel': KDE_KERNEL}

print(bandwidth, FIT_METHOD)
0.6 square_error

7.1 Variability of the Result

In [88]:
%%time
results = Parallel(n_jobs=-1)(delayed(resampled_fitting)(df, FIT_METHOD, NUMBER_OF_GAUSSIAN, config) for i in range(12))                        
for result in results:
    display(pretty_print_gmm(result['gmm']))
    fig,ax = plt.subplots(figsize=(3.5,3.5))
    plot_gmm_ellipses(result['gmm'],ax=ax, xlabel='x'+speed_unit_text, ylabel='y'+speed_unit_text)
    plt.show()
    
    display(gof_df(result['gmm_pdf_result'], result['kde_result']))
    display(gof_df(result['gmm_pdf_result'], kde_result))
    print('')
weight mean_x mean_y sig_x sig_y corr
1 0.424 -0.127 3.758 2.914 2.070 -0.033
2 0.354 3.345 -2.190 1.661 2.754 0.247
3 0.222 -0.421 -1.789 2.970 1.867 -0.465
GMM Plot Result
0.424042026039 [[-0.1266006   3.75809535]] [ 2.06795952  2.91533137] -92.7085077967
0.35414752208 [[ 3.34519023 -2.18960075]] [ 1.58402624  2.79920573] 167.451777493
0.221810451881 [[-0.42141263 -1.78949075]] [ 1.56302665  3.14090039] -112.014512919
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.012 0.061 2.918049e-07 0.033 0.159
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.012 0.051 2.810756e-07 0.032 0.156

weight mean_x mean_y sig_x sig_y corr
1 0.418 -0.016 3.798 2.930 2.037 -0.045
2 0.338 3.327 -2.098 1.635 2.762 0.251
3 0.245 -0.304 -1.824 3.136 2.090 -0.558
GMM Plot Result
0.417638680171 [[-0.0155011   3.79811061]] [ 2.03270994  2.93302529] -93.4843914816
0.337821519768 [[ 3.32663278 -2.09817581]] [ 1.55796998  2.80672389] 167.710809919
0.244539800061 [[-0.30437943 -1.82400982]] [ 1.59227806  3.41593007] -116.61202903
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.980 0.014 0.046 2.667212e-07 0.031 0.152
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.013 0.056 2.830013e-07 0.033 0.157

weight mean_x mean_y sig_x sig_y corr
1 0.419 -0.178 3.732 2.911 2.023 -0.015
2 0.364 3.325 -2.022 1.705 2.822 0.235
3 0.217 -0.451 -1.807 2.978 1.929 -0.518
GMM Plot Result
0.419270858443 [[-0.17803794  3.73184646]] [ 2.0225618   2.91140981] -91.1711232553
0.364005426324 [[ 3.32512478 -2.02158933]] [ 1.63305188  2.86469043] 167.950770166
0.216723715232 [[-0.45147067 -1.80701841]] [ 1.53698741  3.19838863] -114.562074356
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.015 0.072 2.920282e-07 0.033 0.159
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.980 0.015 0.064 2.788392e-07 0.032 0.156

weight mean_x mean_y sig_x sig_y corr
1 0.423 -0.152 3.770 2.888 1.984 -0.017
2 0.364 3.326 -2.123 1.705 2.792 0.239
3 0.213 -0.599 -1.753 2.883 1.891 -0.477
GMM Plot Result
0.422799172863 [[-0.15216718  3.76965221]] [ 1.98363538  2.88847031] -91.2391953187
0.363805437847 [[ 3.32576671 -2.12289963]] [ 1.63004898  2.836917  ] 167.526470176
0.21339538929 [[-0.59938444 -1.75254647]] [ 1.55729592  3.07542533] -113.84214368
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.978 0.016 0.068 3.044830e-07 0.034 0.162
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.016 0.052 2.816597e-07 0.033 0.156

weight mean_x mean_y sig_x sig_y corr
1 0.415 -0.069 3.756 2.915 2.003 -0.028
2 0.335 3.413 -1.987 1.589 2.747 0.194
3 0.251 -0.174 -2.031 3.141 2.163 -0.533
GMM Plot Result
0.414733783001 [[-0.0687966   3.75599821]] [ 2.00101817  2.91589762] -92.0962917946
0.334701620208 [[ 3.41348518 -1.98673221]] [ 1.54492625  2.77189888] 170.657624894
0.250564596791 [[-0.17407267 -2.03106371]] [ 1.67905566  3.42448801] -117.194466936
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.980 0.014 0.030 2.740137e-07 0.033 0.154
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.016 0.034 2.882674e-07 0.033 0.158

weight mean_x mean_y sig_x sig_y corr
1 0.410 -0.197 3.764 2.836 1.999 0.006
2 0.334 3.408 -1.808 1.596 2.883 0.239
3 0.256 -0.111 -1.992 3.113 2.070 -0.529
GMM Plot Result
0.410314197441 [[-0.19701526  3.76391889]] [ 1.99859481  2.83577383] -89.5402598632
0.333940442703 [[ 3.40754595 -1.80755441]] [ 1.53135329  2.91750672] 169.577041935
0.255745359857 [[-0.11085703 -1.99226282]] [ 1.6235572   3.36761147] -115.79600209
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.016 0.063 2.908030e-07 0.033 0.159
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.980 0.016 0.044 2.773427e-07 0.032 0.155

weight mean_x mean_y sig_x sig_y corr
1 0.413 -0.182 3.718 2.891 2.002 -0.022
2 0.342 3.359 -1.980 1.615 2.865 0.247
3 0.245 -0.155 -1.970 3.135 1.987 -0.544
GMM Plot Result
0.412894389973 [[-0.18214832  3.71824073]] [ 2.00071057  2.89157874] -91.698628808
0.342053992701 [[ 3.35876993 -1.98006051]] [ 1.54391541  2.90384244] 168.881441124
0.245051617325 [[-0.15456615 -1.97025785]] [ 1.55036977  3.37199088] -114.513237484
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.981 0.015 0.066 2.592972e-07 0.031 0.150
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.017 0.062 2.830176e-07 0.033 0.157

weight mean_x mean_y sig_x sig_y corr
1 0.414 -0.176 3.748 2.905 2.043 -0.005
2 0.355 3.383 -1.952 1.659 2.747 0.194
3 0.231 -0.320 -1.932 3.033 1.998 -0.523
GMM Plot Result
0.413899516548 [[-0.17613008  3.74823258]] [ 2.0427497   2.90524322] -90.3638025082
0.354815455235 [[ 3.38260952 -1.95178268]] [ 1.61109641  2.77592334] 169.897906183
0.231285028217 [[-0.3198523  -1.93167858]] [ 1.57916033  3.27049819] -115.318068628
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.016 0.088 2.813388e-07 0.032 0.156
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.015 0.050 2.813011e-07 0.032 0.156

weight mean_x mean_y sig_x sig_y corr
1 0.407 -0.078 3.803 2.886 1.993 -0.045
2 0.339 3.403 -1.913 1.623 2.707 0.208
3 0.255 -0.341 -1.877 3.076 2.149 -0.563
GMM Plot Result
0.406613140049 [[-0.07810699  3.80348529]] [ 1.98877558  2.88896709] -93.4152774611
0.338562373986 [[ 3.40308838 -1.91261769]] [ 1.5691169   2.73849416] 169.37491398
0.254824485966 [[-0.34090709 -1.87656628]] [ 1.61160881  3.38818565] -118.485326895
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.017 0.037 2.840563e-07 0.032 0.157
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.980 0.017 0.050 2.775351e-07 0.032 0.155

weight mean_x mean_y sig_x sig_y corr
1 0.419 -0.081 3.809 2.921 2.025 -0.014
2 0.369 3.333 -2.165 1.689 2.745 0.216
3 0.212 -0.715 -1.728 2.775 1.950 -0.463
GMM Plot Result
0.419491136419 [[-0.08077849  3.80941788]] [ 2.02418503  2.92078248] -91.0831588554
0.368923777321 [[ 3.33265312 -2.16472772]] [ 1.62713039  2.78200051] 168.391163592
0.21158508626 [[-0.71524654 -1.72839734]] [ 1.60571923  2.98745957] -116.063123721
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.013 0.044 2.840361e-07 0.032 0.157
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.980 0.013 0.042 2.768643e-07 0.032 0.155

weight mean_x mean_y sig_x sig_y corr
1 0.407 -0.236 3.792 2.795 2.015 0.008
2 0.351 3.399 -1.897 1.644 2.883 0.239
3 0.242 -0.260 -1.935 3.053 1.934 -0.502
GMM Plot Result
0.406822063766 [[-0.23609643  3.79221052]] [ 2.01527736  2.79483355] -89.2914633877
0.350984613086 [[ 3.39921373 -1.89688874]] [ 1.57559258  2.92042776] 169.011856569
0.242193323149 [[-0.26000236 -1.93544093]] [ 1.56755228  3.25661076] -113.368215259
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.014 0.044 2.849025e-07 0.032 0.157
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.980 0.015 0.049 2.778570e-07 0.032 0.155

weight mean_x mean_y sig_x sig_y corr
1 0.428 -0.153 3.690 2.882 2.100 -0.029
2 0.343 3.378 -2.054 1.663 2.751 0.239
3 0.229 -0.268 -1.985 2.985 1.962 -0.533
GMM Plot Result
0.427856796494 [[-0.15296695  3.69014175]] [ 2.09841906  2.88301535] -92.6095883543
0.343183531789 [[ 3.37839568 -2.05364672]] [ 1.59054126  2.79394108] 167.772413822
0.228959671717 [[-0.26813473 -1.98481624]] [ 1.53673678  3.2248676 ] -115.476754605
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.980 0.014 0.055 2.780992e-07 0.032 0.155
R_square K_S Chi_square MSE RMSE / Max RMSE / Mean
0 0.979 0.013 0.060 2.806583e-07 0.032 0.156
Wall time: 14.3 s

7.2 Cross-validation, to select the number of Gaussian

In [89]:
%%time
from sklearn.cross_validation import train_test_split, KFold

## 5-fold cross validation
gaussian_number_range = arange(1,6)
CV_result_train_all,CV_result_test_all =[],[]
number_of_fold = 4
print('Number of train/test dataset', len(df)*(number_of_fold-1)/number_of_fold, len(df)/number_of_fold) 

for number_of_gaussian in gaussian_number_range:
    print( '  ')
    print('Number of gaussian', number_of_gaussian)
    
    kf = KFold(len(df), n_folds=number_of_fold, shuffle=True) 

    CV_result = Parallel(n_jobs=-1)(delayed(fit_per_fold)(df, train_index, test_index, FIT_METHOD, number_of_gaussian, config) for train_index, test_index in kf)                        

    CV_result_train, CV_result_test = list(zip(*CV_result))
    CV_result_train, CV_result_test = list(CV_result_train), list(CV_result_test)
        
    CV_result_train_all.append(CV_result_train)
    CV_result_test_all.append(CV_result_test)
    
    print('Train')
    pretty_pd_display(CV_result_train)
    print('Test')
    pretty_pd_display(CV_result_test)
D:\ProgramData\Anaconda3\lib\site-packages\sklearn\cross_validation.py:44: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)
Number of train/test dataset 27264.0 9088.0
  
Number of gaussian 1
Train
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.125934 0.074892 0.000003 0.113786 0.543696 0.749044
1 0.125861 0.075999 0.000003 0.114172 0.544283 0.747798
2 0.124129 0.074887 0.000003 0.111294 0.539413 0.753627
3 0.125947 0.075695 0.000003 0.113567 0.549458 0.745627
Test
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.128667 0.081582 0.000004 0.113201 0.554201 0.741820
1 0.125211 0.072068 0.000003 0.110081 0.542542 0.754634
2 0.136305 0.073361 0.000004 0.118834 0.557338 0.737238
3 0.131519 0.074462 0.000003 0.114116 0.538168 0.751331
  
Number of gaussian 2
Train
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.052705 0.032472 8.359154e-07 0.055839 0.269305 0.938807
1 0.052060 0.033240 8.209624e-07 0.056035 0.266834 0.939850
2 0.054273 0.034078 8.172016e-07 0.055342 0.266115 0.939622
3 0.053936 0.034069 8.281664e-07 0.055407 0.268003 0.939071
Test
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.059032 0.032052 8.543415e-07 0.057119 0.271991 0.936721
1 0.062133 0.034593 9.278045e-07 0.057358 0.283607 0.931598
2 0.057303 0.034820 9.087865e-07 0.058490 0.281026 0.934523
3 0.056006 0.036610 8.641181e-07 0.057995 0.273698 0.936898
  
Number of gaussian 3
Train
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.047401 0.016179 2.899595e-07 0.032992 0.158688 0.978868
1 0.042688 0.013384 2.740002e-07 0.031770 0.154011 0.980039
2 0.048454 0.014349 2.751484e-07 0.032171 0.154477 0.979686
3 0.039006 0.013582 2.660081e-07 0.031837 0.151895 0.980223
Test
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.068988 0.012082 2.819605e-07 0.032501 0.156026 0.978811
1 0.059442 0.021349 3.866882e-07 0.039173 0.183604 0.971008
2 0.052699 0.023305 3.747775e-07 0.037358 0.180248 0.972987
3 0.042372 0.013228 4.271865e-07 0.039130 0.192421 0.969882
  
Number of gaussian 4
Train
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.037394 0.010601 2.255891e-07 0.028557 0.139868 0.983579
1 0.041641 0.012424 2.291502e-07 0.029552 0.140975 0.983191
2 0.038651 0.008964 2.197404e-07 0.028730 0.137989 0.983790
3 0.032671 0.009958 2.186529e-07 0.028944 0.137746 0.983812
Test
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.051408 0.014838 2.644042e-07 0.033377 0.151421 0.980067
1 0.061836 0.013871 3.234363e-07 0.034041 0.167448 0.976191
2 0.036295 0.011660 2.885172e-07 0.032843 0.158361 0.979119
3 0.038356 0.010949 2.790483e-07 0.031377 0.155406 0.979996
  
Number of gaussian 5
Train
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.048781 0.008012 1.481093e-07 0.023441 0.113343 0.989082
1 0.027209 0.009741 1.538962e-07 0.023640 0.115535 0.988733
2 0.030974 0.009046 1.626136e-07 0.024929 0.118770 0.988076
3 0.023373 0.007864 1.721678e-07 0.025749 0.122145 0.987316
Test
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
0 0.051156 0.009783 2.126864e-07 0.028736 0.135766 0.984573
1 0.033620 0.023907 2.896974e-07 0.034681 0.158455 0.978580
2 0.038986 0.011240 2.583910e-07 0.030302 0.149618 0.980978
3 0.051119 0.010818 2.081652e-07 0.026903 0.134504 0.984866
Wall time: 42.2 s
In [90]:
train_scores_mean, train_scores_std = generate_mean_std_gof(CV_result_train_all)
print('Train gof mean, std')
display(train_scores_mean)

test_scores_mean, test_scores_std = generate_mean_std_gof(CV_result_test_all)
print('Test gof mean, std')
display(test_scores_mean)
Train gof mean, std
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
1 0.125468 0.075368 3.415379e-06 0.113205 0.544213 0.749024
2 0.053243 0.033465 8.255615e-07 0.055656 0.267564 0.939337
3 0.044387 0.014374 2.762790e-07 0.032193 0.154768 0.979704
4 0.037589 0.010487 2.232831e-07 0.028946 0.139144 0.983593
5 0.032584 0.008666 1.591967e-07 0.024440 0.117448 0.988302
Test gof mean, std
Chi_square K_S MSE RMSE / Max RMSE / Mean R_square
1 0.130426 0.075368 3.464302e-06 0.114058 0.548062 0.746256
2 0.058618 0.034519 8.887626e-07 0.057740 0.277581 0.934935
3 0.055875 0.017491 3.676532e-07 0.037040 0.178075 0.973172
4 0.046974 0.012830 2.888515e-07 0.032910 0.158159 0.978843
5 0.043720 0.013937 2.422350e-07 0.030156 0.144586 0.982249
In [91]:
prop_cycle=mpl.rcParams['axes.color_cycle']
gaussian_number_range = train_scores_mean.index
for column, column_name in zip(['R_square','K_S','Chi_square'],["$\ R^2$", "K-S", "$\widetilde{\chi^2} $"]):
    plot(gaussian_number_range, train_scores_mean[column],
             '--', label = 'training', color=prop_cycle[0])
    plt.fill_between(gaussian_number_range, 
                     train_scores_mean[column] - train_scores_std[column],
                     train_scores_mean[column] + train_scores_std[column], 
                     alpha=0.2, color=prop_cycle[0])
    
    plot(gaussian_number_range, test_scores_mean[column],
             '-', label = 'test',color=prop_cycle[1])
    plt.fill_between(gaussian_number_range, 
                 test_scores_mean[column] - test_scores_std[column],
                 test_scores_mean[column] + test_scores_std[column], 
                 alpha=0.2,color=prop_cycle[1])
    plt.xticks(gaussian_number_range)
    print(column)
    plt.locator_params(axis='y', nbins=5)
    plt_configure(xlabel='Number of Gaussian Distributions', ylabel=column_name, 
                  figsize=(3,2), legend={'loc':'best'})
    if column == 'R_square':
        plt.gca().set_ylim(top=1)
    if column == 'K_S' or column == 'Chi_square':
        plt.gca().set_ylim(bottom=0)
    plt.show()
R_square
D:\ProgramData\Anaconda3\lib\site-packages\matplotlib\__init__.py:938: UserWarning: axes.color_cycle is deprecated and replaced with axes.prop_cycle; please use the latter.
  warnings.warn(self.msg_depr % (key, alt_key))
K_S
Chi_square
In [ ]:
# for fig in [fig_hist, fig_kde, fig_em, fig_gmm]:
#     display(fig)
# for fig in [fig_time_variability_3d, fig_time_variability_cdf, fig_time_variability_weibull, 
#             fig_adjecent_variability_3d, fig_adjecent_variability_cdf, fig_adjecent_variability_weibull,]:
#     display(fig)
In [ ]:
import time
save_notebook()
time.sleep(3)
location_name = get_location_name(file_path)
print(location_name)
current_file = 'GMM.ipynb'
output_file = './output_HTML/'+location_name+'.html' 

output_HTML(current_file, output_file)