In [151]:
import pandas as pd
import numpy as np
import re

from dateutil.parser import parse

In [152]:
data = pd.read_csv('Signs.csv')
data.head()


Out[152]:
longtitude latitude OBJECTID SG_KEY_BOR SG_ORDER_N SG_SEQNO_N SG_MUTCD_C SR_DIST SG_SIGN_FC SG_ARROW_D x y SIGNDESC1
0 -73.922335 40.836256 11919717 B P-132428 3 SP-287B 45 NaN NaN 1005740.86711 243957.356623 NO STANDING 10AM-6PM MON THRU FRI
1 -73.922335 40.836256 11919718 B P-132428 4 SP-672G 45 NaN NaN 1005740.86711 243957.356623 EXCEPT
2 -73.922335 40.836256 11919719 B P-132428 5 SP-579G 45 NaN NaN 1005740.86711 243957.356623 AMBULETTE
3 -73.922330 40.836352 11919720 B P-132428 6 SP-287BA 80 NaN S 1005742.32839 243992.461212 NO STANDING 10AM-6PM MON THRU FRI (SINGLE ARROW)
4 -73.922330 40.836352 11919721 B P-132428 7 SP-672G 80 NaN NaN 1005742.32839 243992.461212 EXCEPT

In [153]:
data['SIGNDESC1'].head()


Out[153]:
0                   NO STANDING 10AM-6PM MON THRU FRI
1                                              EXCEPT
2                                           AMBULETTE
3    NO STANDING 10AM-6PM MON THRU FRI (SINGLE ARROW)
4                                              EXCEPT
Name: SIGNDESC1, dtype: object

In [154]:
# https://regex101.com/r/fC0lI5/10
p = re.compile(r'(NOON|MIDNIGHT.*|[01]?[0-9]+:?[0-9]*(?:[AP]MM?)?)\s*(?:-|TO|\s)\s*(NOON|MIDNIGHT|[01]?[0-9]+:?[0-9]*(?:[AP]MM?)?)')

def extract_time(desc, group=1):
    m = p.search(desc)
    if m:
        time = m.group(group)
        if time == 'MIDNIGHT':
            return '12AM'
        elif time == 'MIDNIGHT TO':
            return '12AM'
        elif time == 'NOON':
            return '12PM'
        elif 'MM' in time:
            match_amm_or_pmm = re.compile(r'([0-9])*?([AP]MM?)')
            matched_time = match_amm_or_pmm.search(time)
            if matched_time:
                meridiem = 'AM' if matched_time.group(2) == 'AMM' else 'PM'
                oclock = matched_time.group(1)
                return '{0}{1}'.format(oclock, meridiem)
                
        return m.group(group)
    return np.nan

def from_time(signdesc):
    f_time = extract_time(signdesc, group=1)
    if f_time and f_time is not np.nan:
        return parse(f_time).strftime('%I:%M%p')
    return np.nan

def to_time(signdesc):
    t_time = extract_time(signdesc, group=2)
    if t_time and t_time is not np.nan:
        try:
            return parse(t_time).strftime('%I:%M%p')
        except:
            print(signdesc)
            print(t_time)
            return np.nan
    return np.nan

Special Cases

assert extract_time('1 HR MUNI-METER PARKING 10AM-7PM MON THRU FRI 8AM-7PM SATURDAY W/ SINGLE ARROW') == '' NO PARKING (SANITATION BROOM SYMBOL) 11:30AM TO 1 PM FRIW/ SINGLE ARROW

check if 2 timings is the maximum amount


In [155]:
row = 'NO PARKING (SANITATION BROOM SYMBOL) 7AM-7:30AM EXCEPT SUNDAY'
assert from_time(row) == '07:00AM'
assert to_time(row) == '07:30AM'

special_case1 = 'NO PARKING (SANITATION BROOM SYMBOL) 11:30AM TO 1PM THURS'
assert from_time(special_case1) == '11:30AM'
assert to_time(special_case1) == '01:00PM'

special_case2 = 'NO PARKING (SANITATION BROOM SYMBOL) MOON & STARS (SYMBOLS) TUESDAY FRIDAY MIDNIGHT-3AM'
assert from_time(special_case2) == '12:00AM'
assert to_time(special_case2) == '03:00AM'

special_case3 = 'TRUCK (SYMBOL) TRUCK LOADING ONLY MONDAY-FRIDAY NOON-2PM'
assert from_time(special_case3) == '12:00PM'
assert to_time(special_case3) == '02:00PM'

special_case4 = 'NIGHT REGULATION (MOON & STARS SYMBOLS) NO PARKING (SANITATION BROOM SYMBOL) MIDNIGHT TO-3AM WED & SAT'
assert from_time(special_case4) == '12:00AM'
assert to_time(special_case4) == '03:00AM'

special_case5 = 'NO PARKING (SANITATION BROOM SYMBOL)8AM 11AM TUES & THURS'
assert from_time(special_case5) == '08:00AM'
assert to_time(special_case5) == '11:00AM'

special_case6 = 'NO PARKING (SANITATION BROOM SYMBOL) MONDAY THURSDAY 7AMM-7:30AM'
assert from_time(special_case6) == '07:00AM'
assert to_time(special_case6) == '07:30AM'

In [156]:
def filter_from_time(row):
    if not pd.isnull(row['SIGNDESC1']):
        return from_time(row['SIGNDESC1'])
    return np.nan

In [157]:
def filter_to_time(row):
    if not pd.isnull(row['SIGNDESC1']):
        return to_time(row['SIGNDESC1'])
    return np.nan

In [158]:
data['FROM_TIME'] = data.apply(filter_from_time, axis=1)

In [159]:
data['TO_TIME'] = data.apply(filter_to_time, axis=1)


HYLAN BLVD (9 0'CLOCK ARROW)
0

In [160]:
data[['SIGNDESC1', 'FROM_TIME', 'TO_TIME']].head(10)


Out[160]:
SIGNDESC1 FROM_TIME TO_TIME
0 NO STANDING 10AM-6PM MON THRU FRI 10:00AM 06:00PM
1 EXCEPT NaN NaN
2 AMBULETTE NaN NaN
3 NO STANDING 10AM-6PM MON THRU FRI (SINGLE ARROW) 10:00AM 06:00PM
4 EXCEPT NaN NaN
5 AMBULETTE NaN NaN
6 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... 11:30AM 01:00PM
7 OTHER TIMES 1 HOUR PARKING 9AM-7PM EXCEPT SUND... 09:00AM 07:00PM
8 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... 11:30AM 01:00PM
9 NO PARKING PASSENGER LOADING ZONE W/ SINGLE ARROW NaN NaN

Find out if any rows has NaN

Want to find out if any rows has NaN from from_time and to_time but has timing in SIGNDESC1


In [161]:
rows_with_AM_PM_but_time_NaN = data[(data['FROM_TIME'].isnull() | data['FROM_TIME'].isnull()) & (data['SIGNDESC1'].str.contains('[0-9]+(?:[AP]M)'))]

In [162]:
len(rows_with_AM_PM_but_time_NaN)


Out[162]:
6

In [163]:
rows_with_AM_PM_but_time_NaN[['SIGNDESC1', 'FROM_TIME', 'TO_TIME']]


Out[163]:
SIGNDESC1 FROM_TIME TO_TIME
180670 TRUCK (SYMBOL) TRUCK LOADING ONLY MONDAY-FRIDA... NaN NaN
212089 NO PARKING (SANITATION BROOM SYMBOL) TUESDAY F... NaN NaN
258938 NO PARKING (SANITATION BROOM SYMBOL) TUESDAY F... NaN NaN
258942 NO PARKING (SANITATION BROOM SYMBOL) TUESDAY F... NaN NaN
258944 NO PARKING (SANITATION BROOM SYMBOL) TUESDAY F... NaN NaN
283262 6 HMP 7:30AM=7PM EXCEPT SUNDAY NaN NaN

In [164]:
data.iloc[180670, data.columns.get_loc('SIGNDESC1')]


Out[164]:
'TRUCK (SYMBOL) TRUCK LOADING ONLY MONDAY-FRIDAY 9AM-=4PM'

In [165]:
data.iloc[180670, data.columns.get_loc('FROM_TIME')] = '9AM'
data.iloc[180670, data.columns.get_loc('TO_TIME')] = '4AM'

In [166]:
data.iloc[212089, data.columns.get_loc('SIGNDESC1')]


Out[166]:
'NO PARKING (SANITATION BROOM SYMBOL) TUESDAY FRIDAY 10A M-11:30AM'

In [167]:
data.iloc[212089, data.columns.get_loc('FROM_TIME')] = '10AM'
data.iloc[212089, data.columns.get_loc('TO_TIME')] = '11:30AM'

In [168]:
data.iloc[258938, data.columns.get_loc('SIGNDESC1')]


Out[168]:
'NO PARKING (SANITATION BROOM SYMBOL) TUESDAY FRIDAY 10A M-11:30AM'

In [169]:
data.iloc[258938, data.columns.get_loc('FROM_TIME')] = '10AM'
data.iloc[258938, data.columns.get_loc('TO_TIME')] = '11:30AM'

In [170]:
data.iloc[258942, data.columns.get_loc('SIGNDESC1')]


Out[170]:
'NO PARKING (SANITATION BROOM SYMBOL) TUESDAY FRIDAY 10A M-11:30AM'

In [171]:
data.iloc[258942, data.columns.get_loc('FROM_TIME')] = '10AM'
data.iloc[258942, data.columns.get_loc('TO_TIME')] = '11:30AM'

In [172]:
data.iloc[258944, data.columns.get_loc('SIGNDESC1')]


Out[172]:
'NO PARKING (SANITATION BROOM SYMBOL) TUESDAY FRIDAY 10A M-11:30AM'

In [173]:
data.iloc[258944, data.columns.get_loc('FROM_TIME')] = '10AM'
data.iloc[258944, data.columns.get_loc('TO_TIME')] = '11:30AM'

In [174]:
data.iloc[283262, data.columns.get_loc('SIGNDESC1')]


Out[174]:
'6 HMP 7:30AM=7PM EXCEPT SUNDAY'

In [175]:
data.iloc[283262, data.columns.get_loc('FROM_TIME')] = '6AM'
data.iloc[283262, data.columns.get_loc('TO_TIME')] = '7:30AM'

Confirm that every row has from_time and to_time


In [176]:
rows_with_AM_PM_but_time_NaN = data[(data['FROM_TIME'].isnull() | data['FROM_TIME'].isnull()) & (data['SIGNDESC1'].str.contains('[0-9]+(?:[AP]M)'))]
len(rows_with_AM_PM_but_time_NaN)


Out[176]:
0

In [177]:
data[['SIGNDESC1', 'FROM_TIME', 'TO_TIME']]


Out[177]:
SIGNDESC1 FROM_TIME TO_TIME
0 NO STANDING 10AM-6PM MON THRU FRI 10:00AM 06:00PM
1 EXCEPT NaN NaN
2 AMBULETTE NaN NaN
3 NO STANDING 10AM-6PM MON THRU FRI (SINGLE ARROW) 10:00AM 06:00PM
4 EXCEPT NaN NaN
5 AMBULETTE NaN NaN
6 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... 11:30AM 01:00PM
7 OTHER TIMES 1 HOUR PARKING 9AM-7PM EXCEPT SUND... 09:00AM 07:00PM
8 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... 11:30AM 01:00PM
9 NO PARKING PASSENGER LOADING ZONE W/ SINGLE ARROW NaN NaN
10 NO PARKING PASSENGER LOADING ZONE W/ SINGLE ARROW NaN NaN
11 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... 11:30AM 01:00PM
12 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... 11:30AM 01:00PM
13 NO PARKING ANYTIME (SINGLE ARROW) NaN NaN
14 NO PARKING ANYTIME (SINGLE ARROW) NaN NaN
15 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... 11:30AM 01:00PM
16 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... 11:30AM 01:00PM
17 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... 11:30AM 01:00PM
18 BUS LAYOVER AREA NO STANDING ANYTIME (NO ENGI... NaN NaN
19 BUS LAYOVER AREA NO STANDING ANYTIME (NO ENGI... NaN NaN
20 NO PARKING (SANITATION BROOM SYMBOL) 7:30-8AM ... 07:30AM 08:00AM
21 1 HOUR PARKING 8AM-7PM EXCEPT SUNDAY 08:00AM 07:00PM
22 NO PARKING (SANITATION BROOM SYMBOL) 7:30-8AM ... 07:30AM 08:00AM
23 1 HOUR PARKING 8AM-7PM EXCEPT SUNDAY 08:00AM 07:00PM
24 NO PARKING (SANITATION BROOM SYMBOL) 7:30-8AM ... 07:30AM 08:00AM
25 1 HOUR PARKING 8AM-7PM EXCEPT SUNDAY 08:00AM 07:00PM
26 NO PARKING (SANITATION BROOM SYMBOL) 8-8:30AM ... 12:00AM 08:30AM
27 NO PARKING (SANITATION BROOM SYMBOL) 8-8:30AM ... 12:00AM 08:30AM
28 1 HOUR PARKING 8:30AM-7PM EXCEPT SUNDAY W/SING... 08:30AM 07:00PM
29 NO PARKING (SANITATION BROOM SYMBOL) 8-8:30AM ... 12:00AM 08:30AM
... ... ... ...
384892 4 HR MUNI-METER PARKING 9AM-7PM EXCEPT SUNDAY ... 09:00AM 07:00PM
384893 NO STANDING ANYTIME (SINGLE ARROW) NaN NaN
384894 4 HR MUNI-METER PARKING 9AM-7PM EXCEPT SUNDAY ... 09:00AM 07:00PM
384895 NO STANDING ANYTIME NaN NaN
384896 BUS STOP SIGN (BUS & HANDICAP SYMBOLS) NO STAN... NaN NaN
384897 M 18 LTD 8 STREET/4 AVENUE (TYPICAL BUS ROUTE... NaN NaN
384898 14 STREET & UNION SQ (BOTTOM LOCATION PANEL) NaN NaN
384899 2 HR MUNI-METER PARKING 8AM-7PM EXCEPT SUNDAY 08:00AM 07:00PM
384900 2 HR MUNI-METER PARKING 8AM-7PM EXCEPT SUNDAY 08:00AM 07:00PM
384901 NO STANDING ANYTIME (SINGLE ARROW) NaN NaN
384902 2 HR MUNI-METER PARKING 8AM-7PM EXCEPT SUNDAY ... 08:00AM 07:00PM
384903 NO STANDING MONDAY-FRIDAY 7AM-9AM 07:00AM 09:00AM
384904 2 HOUR PARKING 9AM-7PM EXCEPT SUNDAY 09:00AM 07:00PM
384905 NO STANDING ANYTIME NaN NaN
384906 NO STANDING MONDAY-FRIDAY 7AM-9AM 07:00AM 09:00AM
384907 2 HOUR PARKING 9AM-7PM EXCEPT SUNDAY 09:00AM 07:00PM
384908 2 HOUR PARKING 9AM-5PM MON THRU SAT W/SINGLE A... 09:00AM 05:00PM
384909 2 HOUR PARKING 9AM-5PM MON THRU SAT 09:00AM 05:00PM
384910 NO STANDING 4PM-7PM MON THRU FRI 04:00PM 07:00PM
384911 1 HOUR PARKING 8AM-4PM MON THRU FRI 8AM-7PM SA... 08:00AM 04:00PM
384912 NO STANDING 4PM-7PM MON THRU FRI 04:00PM 07:00PM
384913 1 HOUR PARKING 8AM-4PM MON THRU FRI 8AM-7PM SA... 08:00AM 04:00PM
384914 6 HOUR PARKING 8AM-8PM EXCEPT SUNDAY 08:00AM 08:00PM
384915 PAY AT MUNI-METER W/ SINGLE ARROW NYC PARKING ... NaN NaN
384916 6 HOUR PARKING 8AM-8PM EXCEPT SUNDAY 08:00AM 08:00PM
384917 PAY AT MUNI-METER W/ SINGLE ARROW NYC PARKING ... NaN NaN
384918 6 HOUR PARKING 8AM-8PM EXCEPT SUNDAY 08:00AM 08:00PM
384919 PAY AT MUNI-METER W/ SINGLE ARROW NYC PARKING ... NaN NaN
384920 6 HOUR PARKING 8AM-8PM EXCEPT SUNDAY W/SINGLE ... 08:00AM 08:00PM
384921 PAY AT MUNI-METER W/ SINGLE ARROW NYC PARKING ... NaN NaN

384922 rows × 3 columns

Day of the week


In [178]:
data['SIGNDESC1'].head(20)


Out[178]:
0                     NO STANDING 10AM-6PM MON THRU FRI
1                                                EXCEPT
2                                             AMBULETTE
3      NO STANDING 10AM-6PM MON THRU FRI (SINGLE ARROW)
4                                                EXCEPT
5                                             AMBULETTE
6     NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T...
7     OTHER TIMES 1 HOUR PARKING 9AM-7PM EXCEPT SUND...
8     NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T...
9     NO PARKING PASSENGER LOADING ZONE W/ SINGLE ARROW
10    NO PARKING PASSENGER LOADING ZONE W/ SINGLE ARROW
11    NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T...
12    NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T...
13                    NO PARKING ANYTIME (SINGLE ARROW)
14                    NO PARKING ANYTIME (SINGLE ARROW)
15    NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T...
16    NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T...
17    NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T...
18    BUS LAYOVER AREA NO STANDING ANYTIME  (NO ENGI...
19    BUS LAYOVER AREA NO STANDING ANYTIME  (NO ENGI...
Name: SIGNDESC1, dtype: object

In [179]:
#https://regex101.com/r/fO4zL8/3
regex_to_extract_days_idv_days = r'\b((?:(?:MON|MONDAY|TUES|TUESDAY|WED|WEDNESDAY|THURS|THURSDAY|FRI|FRIDAY|SAT|SATURDAY|SUN|SUNDAY)\s*)+)(?=\s|$)'
regex_to_extract_days_with_range = r'(MON|TUES|WED|THURS|FRI|SAT|SUN)\s(THRU|\&)\s(MON|TUES|WED|THURS|FRI|SAT|SUN)'

def extract_day(signdesc):
    days = ['MON', 'TUES', 'WED', 'THURS', 'FRI', 'SAT', 'SUN']
    p_idv_days = re.compile(regex_to_extract_days_idv_days)
    m_idv_days = p_idv_days.search(signdesc)
    
    p_range_days = re.compile(regex_to_extract_days_with_range)
    m_range_days = p_range_days.search(signdesc)
    
    if 'EXCEPT SUN' in signdesc:
        return ', '.join(days[:6])
    
    if 'INCLUDING SUNDAY' in signdesc:
        return ', '.join(days)
    
    if 'FRIW/' in signdesc:
        return ', '.join(['FRI'])
    
    if ('THRU' in signdesc) and m_range_days:
        from_day = m_range_days.group(1)
        to_day = m_range_days.group(3)

        idx_frm_d = days.index(from_day)
        idx_to_d = days.index(to_day)
        return ', '.join([days[n] for n in range(idx_frm_d, idx_to_d + 1)])
    
    if ('&' in signdesc) and m_range_days:
        from_day = m_range_days.group(1)
        to_day = m_range_days.group(3)
        
        return ', '.join([from_day, to_day])
    
    if m_idv_days:
        days = m_idv_days.group(1)
        d = []
        for day in days.split(' '):
            if len(day) > 3:
                if day in ['MONDAY', 'WEDNESDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY']:
                    d.append(day[:3])
                if day in ['TUESDAY']:
                    d.append(day[:4])
                if day in ['THURSDAY']:
                    d.append(day[:5])
            else:
                d.append(day)
                    
        return ', '.join(d)
            
    return np.nan

In [180]:
def filter_days(row):
    if not pd.isnull(row['SIGNDESC1']):
        return extract_day(row['SIGNDESC1'])
    return np.nan

In [181]:
assert extract_day('NO STANDING 11AM-7AM MON SAT') == "MON, SAT"
assert extract_day('NO STANDING MON FRI 7AM-9AM') == "MON, FRI"
assert extract_day('2 HOUR PARKING 9AM-5PM MON THRU SAT') == "MON, TUES, WED, THURS, FRI, SAT"
assert extract_day('1 HOUR PARKING 8AM-7PM EXCEPT SUNDAY') == "MON, TUES, WED, THURS, FRI, SAT"
assert extract_day('NO PARKING 10PM-8AM INCLUDING SUNDAY') == "MON, TUES, WED, THURS, FRI, SAT, SUN"
assert extract_day('NO PARKING (SANITATION BROOM SYMBOL) MONDAY THURSDAY 9:30AM-11AM') == "MON, THURS"
assert extract_day('NO PARKING (SANITATION BROOM SYMBOL) 11:30AM TO 1 PM FRIW/ SINGLE ARROW') == "FRI"
assert extract_day('NO PARKING (SANITATION BROOM SYMBOL) 8-9:30AM TUES & FRI') == "TUES, FRI"
assert extract_day('NO PARKING (SANITATION BROOM SYMBOL) TUESDAY FRIDAY 11AM-12:30PM') == "TUES, FRI"

In [182]:
data['DAYS'] = data.apply(filter_days, axis=1)

In [183]:
rows_with_days_but_DAYS_NAN = data[data['DAYS'].isnull() & data['SIGNDESC1'].str.contains('\sMON|\sTUES|\sWED|\sTHURS|\sFRI|\sSAT|\sSUN')]

In [184]:
rows_with_days_but_DAYS_NAN[['SIGNDESC1', 'DAYS']]


Out[184]:
SIGNDESC1 DAYS
136362 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
136363 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
136364 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
136365 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
136366 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
136367 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
136368 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
136369 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
258535 WARNING THERE ARE NO TAXI DISPATCHERS AT THIS ... NaN
258537 WARNING THERE ARE NO TAXI DISPATCHERS AT THIS ... NaN
258538 WARNING THERE ARE NO TAXI DISPATCHERS AT THIS ... NaN
258539 WARNING THERE ARE NO TAXI DISPATCHERS AT THIS ... NaN
258541 WARNING THERE ARE NO TAXI DISPATCHERS AT THIS ... NaN
308838 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
308839 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
308840 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN
308841 NO PARKING (SANITATION BROOM SYMBOL) 11:30AM T... NaN

In [185]:
data.iloc[308838, data.columns.get_loc('SIGNDESC1')]


Out[185]:
'NO PARKING (SANITATION BROOM SYMBOL) 11:30AM TO 1PM MON-'

In [186]:
data.head()


Out[186]:
longtitude latitude OBJECTID SG_KEY_BOR SG_ORDER_N SG_SEQNO_N SG_MUTCD_C SR_DIST SG_SIGN_FC SG_ARROW_D x y SIGNDESC1 FROM_TIME TO_TIME DAYS
0 -73.922335 40.836256 11919717 B P-132428 3 SP-287B 45 NaN NaN 1005740.86711 243957.356623 NO STANDING 10AM-6PM MON THRU FRI 10:00AM 06:00PM MON, TUES, WED, THURS, FRI
1 -73.922335 40.836256 11919718 B P-132428 4 SP-672G 45 NaN NaN 1005740.86711 243957.356623 EXCEPT NaN NaN NaN
2 -73.922335 40.836256 11919719 B P-132428 5 SP-579G 45 NaN NaN 1005740.86711 243957.356623 AMBULETTE NaN NaN NaN
3 -73.922330 40.836352 11919720 B P-132428 6 SP-287BA 80 NaN S 1005742.32839 243992.461212 NO STANDING 10AM-6PM MON THRU FRI (SINGLE ARROW) 10:00AM 06:00PM MON, TUES, WED, THURS, FRI
4 -73.922330 40.836352 11919721 B P-132428 7 SP-672G 80 NaN NaN 1005742.32839 243992.461212 EXCEPT NaN NaN NaN

Save to CSV


In [187]:
data.to_csv('Processed_Signs.csv', index=False)

In [ ]: