Kaggle·데이터분석예제

[Kaggle][답]샌프란시스코 범죄 예측(sf-crime)

데이터요리사 2020. 7. 20. 07:59

San Francisco Crime Classification

1. 대회 설명

  • URL: https://www.kaggle.com/c/sf-crime

  • 설명

    1934년부터 1963년까지 샌프란시스코의 알카트라즈섬에 악명 높은 범죄자들을 수용 한 것으로 유명했습니다. 이 대회는 약 12년 동안 샌프란시스코의 모든 지역에서 발생한 범죄 보고서를 제공합니다. 시간과 장소가 주어지면 발생한 범죄의 유형(카테고리)을 예측하여 제출합니다.

  • 키워드

    #분류 # classification

  • 평가방법

    범죄 유형별 범죄 발생 가능성을 확률로 계산하여 제출하면, multi class logarithmic loss를 사용하여 정확도를 측정합니다.

2. 데이터

본 대회는 샌프란시스코 오픈 데이터 SF OpenData에서 제공하는 범죄관련 데이터를 사용합니다.

  • 2003년 1월 1일 ~ 2015년 5월 13일 범죄데이터
  • Training Set: 1,3,5,7 주
  • Test Set: 2,4,6,8 주

  • Dates - 범죄 사건 발생 날짜 및 시간 정보

  • Category - 범죄 사건 카테고리(이 값이 예측할 목표변수)

  • Descript - 범죄 사건에 대한 자세한 설명

  • DayOfWeek - 요일

  • PdDistrict - 경찰서 구역 이름

  • Resolution - 범죄 사건이 해결 된 방법

  • Address - 범죄 사건의 대략적인 주소

  • X - 경도

  • Y - 위도

3. 데이터 전처리

데이터 훑어보기

  1. 데이터 로딩

    (1) 데이터 압축 풀기

    !unzip '/kaggle/input/sf-crime/test.csv'
    !unzip '/kaggle/input/sf-crime/train.csv'
    !unzip '/kaggle/input/sf-crime/sampleSubmission.csv'

    최근들어 이전 대회에 데이터셋이 zip 형태의 파일이 제공되고 있습니다. 데이터셋을 불러오기 위해서는 압축을 해제하는 작업부터 시작해야합니다.

    압축 해제를 한 결과물(csv파일)은 output 폴더에서 확인할 수 있습니다.

(2) csv 파일을 데이터프레임으로 읽기

   train = pd.read_csv('./train.csv')
   test = pd.read_csv('./test.csv')
   submission = pd.read_csv('./sampleSubmission.csv')

읽어드릴 파일의 경로는 Copy file path를 사용하면 확인할 수 있습니다.

  1. 학습 데이터 셋의 상위 5개 항목 출력

    train.head()

    [결과]

      Dates Category Descript DayOfWeek PdDistrict Resolution Address X Y
    0 2015-05-13 23:53:00 WARRANTS WARRANT ARREST Wednesday NORTHERN ARREST, BOOKED OAK ST / LAGUNA ST -122.425892 37.774599
    1 2015-05-13 23:53:00 OTHER OFFENSES TRAFFIC VIOLATION ARREST Wednesday NORTHERN ARREST, BOOKED OAK ST / LAGUNA ST -122.425892 37.774599
    2 2015-05-13 23:33:00 OTHER OFFENSES TRAFFIC VIOLATION ARREST Wednesday NORTHERN ARREST, BOOKED VANNESS AV / GREENWICH ST -122.424363 37.800414
    3 2015-05-13 23:30:00 LARCENY/THEFT GRAND THEFT FROM LOCKED AUTO Wednesday NORTHERN NONE 1500 Block of LOMBARD ST -122.426995 37.800873
    4 2015-05-13 23:30:00 LARCENY/THEFT GRAND THEFT FROM LOCKED AUTO Wednesday PARK NONE 100 Block of BRODERICK ST -122.438738 37.771541
  1. 학습 데이터 셋의 각 필드 데이터 분포(평균, 최소값, 최대값 등)를 살펴보기

    train.describe()

    [결과]

      X Y
    count 878049.000000 878049.000000
    mean -122.422616 37.771020
    std 0.030354 0.456893
    min -122.513642 37.707879
    25% -122.432952 37.752427
    50% -122.416420 37.775421
    75% -122.406959 37.784369
    max -120.500000 90.000000

    수치형 데이터를 포함한 컬럼에 대해서만 요약 값을 출력합니다. 총 878,049개의 학습데이터 셋이 있고, X좌표 Y좌표의 최소값, 최대값, 4분위수 등을 확인할 수 있습니다.

  1. 각 컬럼의 데이터 타입 확인하기

    train.info()

    [결과]

    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 878049 entries, 0 to 878048
    Data columns (total 9 columns):
    Dates         878049 non-null object
    Category      878049 non-null object
    Descript      878049 non-null object
    DayOfWeek     878049 non-null object
    PdDistrict    878049 non-null object
    Resolution    878049 non-null object
    Address       878049 non-null object
    X             878049 non-null float64
    Y             878049 non-null float64
    dtypes: float64(2), object(7)
    memory usage: 60.3+ MB

    X,Y를 제외한 컬럼값이 모두 object 타입입니다. 기계학습을 위해서 사용이 필요한 변수들은 수치형데이터로 변환하는 작업이 필요하겠네요.

  1. 범죄의 범주 'Category'는 어떤 값이 있는지 확인하기

    train['Category'].unique()

    [결과]

    array(['WARRANTS', 'OTHER OFFENSES', 'LARCENY/THEFT', 'VEHICLE THEFT',
           'VANDALISM', 'NON-CRIMINAL', 'ROBBERY', 'ASSAULT', 'WEAPON LAWS',
           'BURGLARY', 'SUSPICIOUS OCC', 'DRUNKENNESS',
           'FORGERY/COUNTERFEITING', 'DRUG/NARCOTIC', 'STOLEN PROPERTY',
           'SECONDARY CODES', 'TRESPASS', 'MISSING PERSON', 'FRAUD',
           'KIDNAPPING', 'RUNAWAY', 'DRIVING UNDER THE INFLUENCE',
           'SEX OFFENSES FORCIBLE', 'PROSTITUTION', 'DISORDERLY CONDUCT',
           'ARSON', 'FAMILY OFFENSES', 'LIQUOR LAWS', 'BRIBERY',
           'EMBEZZLEMENT', 'SUICIDE', 'LOITERING',
           'SEX OFFENSES NON FORCIBLE', 'EXTORTION', 'GAMBLING', 'BAD CHECKS',
           'TREA', 'RECOVERED VEHICLE', 'PORNOGRAPHY/OBSCENE MAT'],
          dtype=object)

데이터 할당/변경하기(create, update)

  1. Dates 필드의 데이터타입을 'datetime64' 타입으로 변경하기

    train['Dates'] = train['Dates'].astype('datetime64')

    범죄 사건 발생 날짜 및 시간 정보를 포함한 'Dates'필드의 값을 연도별, 월별, 일별, 시간별로 분석하기 위해서 datetime64타입으로 변환합니다.

    문자열 파싱을 해서 분석할 수도 있지만, datetime64 타입으로 변환하면 파이썬 내장함수를 사용해서 쉽게 연/월/일/시간별 값을 얻어올 수 있습니다.

  1. 연, 월, 일, 요일, 시, 분값을 새로운 컬럼(year, month, day, dayofweek, hour, minute)을 생성해서 할당하기

    train['year'] = train['Dates'].dt.year
    train['month'] = train['Dates'].dt.month
    train['day'] = train['Dates'].dt.day
    train['dayofweek'] = train['Dates'].dt.dayofweek
    train['hour'] = train['Dates'].dt.hour
    train['minute'] = train['Dates'].dt.minute

[결과]

본 글에서는 train 데이터 셋 전처리에 대해서만 정리했습니다. 실제 캐글 데이터 전처리시, train데이터와 test데이터가 모두 동일한 형태로 변환할 수 있도록 함께 처리합니다.

  1. 범죄가 발생한 경도, 위도 값을 나타내는 X, Y 컬럼의 값을 더한 값을 담은 'X+Y' 컬럼, X, Y의 차이 값을 담은 'X-Y' 컬럼을 생성하기

    train['X+Y'] = train['X'] + train['Y']
    train['X-Y'] = train['X'] - train['Y']

[결과]

  1. n_days라는 컬럼을 생성하고, 일별 d-day를 계산하여 입력하기
    예: 범죄 첫발생일: 0, 다음 발생일: 1

    train['n_days'] = (train['Dates'].dt.date - train['Dates'].dt.date.min()).apply(lambda x: x.days)
    test['n_days'] = (test['Dates'].dt.date - test['Dates'].dt.date.min()).apply(lambda x: x.days)
  1. 변수 y를 선언해서 학습할 목표변수(=종속변수)인 Category 필드값을 담기

    y = train['Category']

데이터 선택하기(select)

  1. 연도별(year) 범죄 발생 횟수를 알아보기

    pd.value_counts(train['year']).sort_index()

    .sort_index()는 연도순대로 출력하기 위해 호출하였습니다.

    groupby()를 사용하는 방법은 아래, 월별 범죄횟수를 출력할 때 확인해보겠습니다.

  1. 월별(month) 범죄 발생 횟수를 알아보기

    1) value_counts를 사용하는 방법

    pd.value_counts(train['month']).sort_index()

    [결과]

    1     73536
    2     70813
    3     76320
    4     78096
    5     79644
    6     70892
    7     69971
    8     68540
    9     71982
    10    80274
    11    72975
    12    65006
    Name: month, dtype: int64

2) groupby를 사용하는 방법

   train.groupby('month').size()

[결과]

   1     73536
   2     70813
   3     76320
   4     78096
   5     79644
   6     70892
   7     69971
   8     68540
   9     71982
   10    80274
   11    72975
   12    65006
   dtype: int64

train 데이터필드를 'month' 필드를 기준으로 그룹핑하고, 그룹별 개수를 출력하기 위해 .size()를 호출합니다.

  1. 요일별(DayOfWeek) 범죄 발생 횟수를 알아보기

    pd.value_counts(train['DayOfWeek'])
  1. 카테고리별(Category) 범죄 발생 횟수를 알아보기

    pd.value_counts(train['Category'])
  1. null값이 포함된 데이터 필드가 있는지 확인하기

    df.isnull().any().sum()

데이터 시각화

  1. 라이브러리 import

    import seaborn as sns
    import matplotlib.pylab as plt
    1. 월별 범죄율 시각화하기
    sns.barplot(x=train.groupby('month').size().index, y=train.groupby('month').size().values -62500)

     

sns.barplot(x=train.groupby('year').size().index, y=train.groupby('year').size().values - 40000)

 

sns.barplot(x=train.groupby('day').size().index, y=train.groupby('day').size().values)

sns.barplot(x=train.groupby('dayofweek').size().index, y=train.groupby('dayofweek').size().values - 110000)

 

plt.subplots(figsize = (20,12))
sns.barplot(x=train.groupby('Category').size().index, y=train.groupby('Category').size().values)
plt.xticks(rotation=70)

데이터 삭제하기(delete)

  1. 'Dates','Category','Descript','DayOfWeek','Resolution' 컬럼 삭제하기

    train = train.drop(['Dates','Category','Descript','DayOfWeek','Resolution'], axis=1)

학습용, 테스트용 데이터 셋 분리하기

1.

from sklearn.model_selection import train_test_split
x_train, x_valid, y_train, y_valid = train_test_split(train, y, test_size=0.2, random_state = 5, stratify = y)

 

728x90