0% found this document useful (0 votes)
7 views14 pages

NYC 311 Request Analysis with Matplotlib

Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views14 pages

NYC 311 Request Analysis with Matplotlib

Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Customer Services Request Analysis

In [1]:
#import library
import pandas as pd
import numpy as np
import matplotlib as mpl
from matplotlib import pyplot as plt
%matplotlib inline
[Link](['fivethirtyeight'])
[Link]['[Link]'] = 3
import warnings
[Link]("ignore")
import [Link] as stats
import [Link] as sm
from [Link] import ols
Import NYC request
In [2]:
# read data set 311 NYC service request.
df = pd.read_csv('C:\\rohit\\simple\\Data Science with Python\\practice
project1\\311_Service_Requests_from_2010_to_Present.csv', header=0,
sep=',', parse_dates=['Created Date', 'Closed Date', 'Resolution Action
Updated Date'],index_col='Unique Key')
Covert the columns ‘Created Date’ and Closed Date’ to datetime datatype and create a new column
‘Request_Closing_Time’

Remove null and junk data like closed date < create date , Borough = 'Unspecidfied'
In [3]:
#Prepare data
def prepareData(df):
df['Resolution_Time'] = (df['Closed Date'] - df['Created
Date']).dt.total_seconds() ####days/3600
df_clean=df[df['Resolution_Time'].notnull()]
df_perfect = df_clean[df_clean['Closed Date'] >= df_clean['Created
Date']]
df_perfect['Day of Week'] = df_perfect['Created Date'].[Link]
df_perfect['Day of Month'] = df_perfect['Created Date'].[Link]
df_perfect['Month'] = df_perfect['Created Date'].[Link]
df_perfect['Year'] = df_perfect['Created Date'].[Link]
df_perfect=df_perfect[df_perfect.Borough!='Unspecified']
return df_perfect
In [4]:
#shape
df_perfect = prepareData(df)
df_perfect.shape
Out[4]:
(298068, 57)
Major Insights Patterns.
In [5]:
#Most frequent Complaints
(df_perfect['Complaint Type'].value_counts()).head().plot(kind='bar',
figsize=(10,6), title = 'Most common Complaints')
Out[5]:
<[Link]._subplots.AxesSubplot at 0x1f1e42cbe48>

In [6]:
#Least frequent Complaints
(df_perfect['Complaint Type'].value_counts()).tail().plot(kind='bar',
figsize=(10,6), title = 'Least frequent Complaints')
Out[6]:
<[Link]._subplots.AxesSubplot at 0x1f1dc8b2688>
In [7]:
# complaints distribution across Boroughs
colors =
['#639ace','#ca6b39','#7f67ca','#5ba85f','#c360aa','#a7993f','#cc566a']
df_perfect['Borough'].value_counts().plot(kind='pie',autopct='%1.1f%%',
explode = (0.15, 0, 0, 0, 0), startangle=45,
shadow=False, colors = colors,
figsize = (8,6))
#[Link](title='BOROUGH', loc='upper right', bbox_to_anchor=(1.5,1))
[Link]('equal')
[Link]('# complaints distribution across Boroughs\n')
plt.tight_layout()
[Link]()
In [8]:
#Analysis for Brooklyn borough which has highest number of complains
df_Brooklyn = df_perfect[df_perfect['Borough']=='BROOKLYN']
In [9]:
#shape
df_Brooklyn.shape
Out[9]:
(98295, 57)
In [10]:
(df_Brooklyn['Complaint Type'].value_counts()).head(25).plot(kind='bar',
figsize=(10,6),title =
'Most Frequent Complaints in Brooklyn')
Out[10]:
<[Link]._subplots.AxesSubplot at 0x1f1e01db888>
In [11]:
#location type vs complaints
(df_Brooklyn['Location Type'].value_counts()).head().plot(kind='bar',
figsize=(10,6),title =
'Location Type vs # Complaints')
Out[11]:
<[Link]._subplots.AxesSubplot at 0x1f1dc09c648>
In [12]:
#Anlysis of Most Frequent complaint in Brooklyn
df_perfect[df_perfect['Complaint Type'] == 'Blocked Driveway']
['Descriptor'].value_counts()
Out[12]:
No Access 56786
Partial Access 19967
Name: Descriptor, dtype: int64
In [13]:
df_Brook_blocked = df_Brooklyn[df_Brooklyn['Complaint Type'] == 'Blocked
Driveway']
In [14]:
df_Brook_blocked.plot(
kind='hexbin', x='Longitude', y='Latitude', gridsize=40,title =
'Blocked driveway issues concentration across Brooklyn\n',
colormap='jet', mincnt=1, figsize=(10,6)).axis('equal')
Out[14]:
(-74.04069667018493, -73.85577605981507, 40.57286021, 40.73822772)
In [15]:
df_Brook_blocked['Month'].value_counts().plot(kind = 'bar',figsize=(10,6),
title = 'Volume of Blocked driveway issues by Month\n')
Out[15]:
<[Link]._subplots.AxesSubplot at 0x1f1dc13ef88>

‘Request_Closing_Time’ in Seconds, grouping them for different locations, order by complaint type
In [16]:
df_avg_res_time_city = df_perfect.groupby(['City','Complaint
Type']).Resolution_Time.mean()
#df_perfect.sort_values('Complaint Type').groupby('City')
#
df_avg_res_time_city.head(25)
Out[16]:
City Complaint Type
ARVERNE Animal Abuse 7753.052632
Blocked Driveway 9093.485714
Derelict Vehicle 10685.592593
Disorderly Youth 12928.500000
Drinking 859.000000
Graffiti 5520.000000
Homeless Encampment 6533.250000
Illegal Parking 8338.913793
Noise - Commercial 8234.000000
Noise - House of Worship 5623.909091
Noise - Park 4620.000000
Noise - Street/Sidewalk 7172.620690
Noise - Vehicle 6695.571429
Panhandling 3720.000000
Urinating in Public 2491.000000
Vending 1740.000000
ASTORIA Animal Abuse 18000.608000
Bike/Roller/Skate Chronic 6261.533333
Blocked Driveway 17338.024064
Derelict Vehicle 34881.299145
Disorderly Youth 10449.333333
Drinking 17000.714286
Graffiti 50742.250000
Homeless Encampment 17703.312500
Illegal Fireworks 9984.500000
Name: Resolution_Time, dtype: float64
Average response time across complaint types in seconds
In [17]:
#Average response time in seconds across complaint types
df_avg_res_time = df_perfect.groupby('Complaint
Type').Resolution_Time.mean().sort_values(ascending=True)
df_avg_res_time.head(21)
Out[17]:
Complaint Type
Posting Advertisement 7112.891975
Illegal Fireworks 9940.101190
Noise - Commercial 11291.632884
Noise - House of Worship 11495.874058
Noise - Park 12246.158157
Noise - Street/Sidewalk 12377.738882
Traffic 12415.252002
Disorderly Youth 12810.902098
Noise - Vehicle 12918.914430
Urinating in Public 13055.991554
Bike/Roller/Skate Chronic 13523.545024
Drinking 13879.309748
Vending 14449.060358
Squeegee 14564.250000
Homeless Encampment 15716.052536
Panhandling 15741.963934
Illegal Parking 16149.479466
Blocked Driveway 17057.298659
Animal Abuse 18768.513712
Graffiti 25744.504425
Derelict Vehicle 26445.913579
Name: Resolution_Time, dtype: float64
From the above data null hypothesis can be rejected . Since the average response time across
complaint type are not [Link] Hypothesis : Average response time across complaint type are
equal. Alternate Hypothesis : Average response time across complaint type are equal
Following complains have resolution times which are very close. Disorderly Youth 12810.902098
Noise - Vehicle 12918.914430 One group can be formed for these complaints and one way Anova for
this can be performed
In [18]:
df_dis_youth = df_perfect[df_perfect['Complaint Type']=='Disorderly Youth']
df_dis_youth = df_dis_youth.loc[:,['Resolution_Time']]
df_dis_youth.head()
#df_dis_youth.columns
#df_avg_res_time = df_avg_res_time.to_frame()
#df_avg_res_time.columns()
#df_dis_youth.Complaint [Link]()
Out[18]:

Resolution_Time

Unique
Key

32274507 713.0

32244468 4605.0

32225263 2345.0

32227341 19415.0

32191432 6849.0
Resolution_Time

Unique
Key

In [19]:
df_noise_veh = df_perfect[df_perfect['Complaint Type']=='Noise - Vehicle']
df_noise_veh = df_noise_veh.loc[:,['Resolution_Time']]
df_noise_veh.head()
#df_noise_veh.columns
#df_noise_veh.info()
Out[19]:

Resolution_Time

Unique
Key

32307159 22949.0

32308722 7254.0

32308107 11319.0

32308108 10937.0

32306622 2615.0

In [20]:
df_type_res = df_perfect.loc[:, ['Complaint Type','Resolution_Time']]
df_type_res.head()
df_type_res.columns
Out[20]:
Index(['Complaint Type', 'Resolution_Time'], dtype='object')
In [21]:
# stats f_oneway functions takes the groups as input and returns F and P-
value
fvalue, pvalue = stats.f_oneway(df_dis_youth, df_noise_veh)
pvalue
Out[21]:
array([0.91269878])
Null hypothesis to be accepted for Disorderly Youth and Noise - Vehicle p-value close to 1
One Way Anova for Posting Advertisement and Derelict Vehicle
In [36]:
df_post_ad = df_perfect[df_perfect['Complaint Type']=='Posting
Advertisement']
df_post_ad = df_post_ad.loc[:,['Resolution_Time']]
df_post_ad.head()
Out[36]:

Resolution_Time

Unique
Key

32306752 7596.0

32307464 7745.0

32308949 7834.0

32307323 8042.0

32306034 8137.0

In [33]:
df_der_veh = df_perfect[df_perfect['Complaint Type']=='Derelict Vehicle']
df_der_veh = df_der_veh.loc[:,['Resolution_Time']]
df_der_veh.head()
Out[33]:
Resolution_Time

Unique
Key

32309424 37763.0

32306497 14221.0

32305124 4913.0

32308002 14879.0

32305798 2712.0

In [34]:
# stats f_oneway functions takes the groups as input and returns F and P-
value
fvalue, pvalue = stats.f_oneway(df_post_ad, df_der_veh)
pvalue
Out[34]:
array([7.28776953e-35])
Null hypothesis for Posting Advertisement and Derelict Vehicle to be rejected p-value < 0.05
Anova table for complain type and resolution time
In [29]:
# get ANOVA table for complain type and resolution time

# reshape the d dataframe suitable for statsmodels package


df_perfect['Complaint_Type']=df_perfect['Complaint Type']
df_type_res = df_perfect.loc[:, ['Complaint_Type','Resolution_Time']]
#Complaint Type
# Ordinary Least Squares (OLS) model
model = ols('Resolution_Time ~ Complaint_Type', data=df_type_res).fit()
anova_table = [Link].anova_lm(model, typ=2)
anova_table
Out[29]:
s P
u R
m d (
F
_ f >
s F
q )

C
o 3
m . 4
p 7 1
l 8 0
a 4 2 .
0
i 8 0 2
.
n 3 . 5
0
t 9 0 8
_ e 5
T + 9
y 1 8
p 2
e

1
.
R 3 2
e 7 9
s 4 8
N N
i 8 0
a a
d 1 4
N N
u 6 7
a e .
l + 0
1
4

Null Hypothesis to be rejected since p-value < 0.05


Crosstab and Chi Square test for Location and Complaint type
In [30]:
df_city_type = [Link](df_perfect.City , df_perfect.Complaint_Type)
In [31]:
# chi-squared test with similar proportions
from [Link] import chi2_contingency
from [Link] import chi2
# contingency table
table = df_city_type
#print(table)
stat, p, dof, expected = chi2_contingency(table)
print('dof=%d' % dof)
print(expected)
# interpret test-statistic
prob = 0.95
critical = [Link](prob, dof)
print('probability=%.3f, critical=%.3f, stat=%.3f' % (prob, critical,
stat))
if abs(stat) >= critical:
print('Dependent (reject H0)')
else:
print('Independent (fail to reject H0)')
# interpret p-value
alpha = 1.0 - prob
print('significance=%.3f, p=%.3f' % (alpha, p))
if p <= alpha:
print('Dependent (reject H0)')
else:
print('Independent (fail to reject H0)')
dof=1040
[[5.73350737e+00 3.11515400e-01 5.66574169e+01 ... 3.31741755e+00
4.37007385e-01 2.80068584e+00]
[1.64968644e+02 8.96314763e+00 1.63018841e+03 ... 9.54511504e+01
1.25738943e+01 8.05833700e+01]
[1.86599603e+01 1.01384103e+00 1.84394139e+02 ... 1.07966862e+01
1.42226040e+00 9.11495938e+00]
...
[6.41892211e+01 3.48755650e+00 6.34305536e+02 ... 3.71399974e+01
4.89249632e+00 3.13549511e+01]
[9.23615914e+01 5.01822989e+00 9.12699480e+02 ... 5.34405809e+01
7.03979170e+00 4.51165029e+01]
[3.12736765e+00 1.69917491e-01 3.09040456e+01 ... 1.80950048e+00
2.38367665e-01 1.52764682e+00]]
probability=0.950, critical=1116.137, stat=110425.867
Dependent (reject H0)
significance=0.050, p=0.000
Dependent (reject H0)

You might also like