본문 바로가기

Data Science : Project/개인 프로젝트

캐글 샌프란시스코 범죄발생률 예측 : EDA

반응형

 

 

이 예측의 목적은, feature와 같은 정보가 있을 때 어떤 종류의 범죄가 발생할 확률이 얼마인지 예측하는 것이다.

 

파이썬으로 진행하였고,

데이터 분석 강의 4주차를 마무리하고 캐글에 최종적으로 제출한 버전을 기반으로 코드를 설명했다.

(중간 과정이 궁금하다면 github를 참고! github.com/helloMinji/Kaggle_crime_SanFrancisco )

 

helloMinji/Kaggle_crime_SanFrancisco

[Kaggle] 샌프란시스코에서 발생한 범죄 종류 예측. Contribute to helloMinji/Kaggle_crime_SanFrancisco development by creating an account on GitHub.

github.com

 

 

 

 


데이터 설명

  • Dates - 범죄가 발생한 날짜와 시간
  • Category - 범죄의 세부적인 종류. train에만 존재 → label
  • Descript - 범죄의 세부정보. train에만 존재
  • DayOfWeek - 범죄가 발생한 요일
  • PdDistrict - 범죄를 관할하는 경찰서의 이름
  • Resolution - 범죄의 상태, 범죄가 해결되었는지 여부. train에만 존재
  • Address - 범죄가 발생한 구체적인 주소
  • X - 범죄가 발생한 좌표의 경도
  • Y - 범죄가 발생한 좌표의 위

train에만 존재하는 Descript, Resolution은 feature로 쓰지 않는다.

 

 

 


EDA

  Dates

train["Dates"] = pd.to_datetime(train["Dates"])

train["Dates-year"] = train["Dates"].dt.year
train["Dates-month"] = train["Dates"].dt.month
train["Dates-day"] = train["Dates"].dt.day
train["Dates-hour"] = train["Dates"].dt.hour
train["Dates-minute"] = train["Dates"].dt.minute
train["Dates-second"] = train["Dates"].dt.second

print(train.shape)
train[["Dates","Dates-year","Dates-month","Dates-day","Dates-hour","Dates-minute","Dates-second"]].head()

# 시각화
figure, ((ax1, ax2, ax3), (ax4, ax5, ax6)) = plt.subplots(nrows=2, ncols=3)

figure.set_size_inches(18,8)

sns.countplot(data=train, x="Dates-year", ax=ax1)
sns.countplot(data=train, x="Dates-month", ax=ax2)
sns.countplot(data=train, x="Dates-day", ax=ax3)
sns.countplot(data=train, x="Dates-hour", ax=ax4)
sns.countplot(data=train, x="Dates-minute", ax=ax5)
sns.countplot(data=train, x="Dates-second", ax=ax6)

분, 초, 일(31일을 제외하면)은 범죄의 발생빈도를 판가름하는데 별 영향이 없다.

그리고 분은 일부 시간만 많이 나타나는 걸로 봐서, 대표값으로 처리했을 가능성이 있다. (3분5분, 17분20분 등)

하지만 그 외의 시간 컬럼은 범죄 발생빈도에 큰 영향이 있다.

 

 

 2  X, Y

sns.lmplot(data=train, x="X", y="Y", fit_reg = False)

# outlier
train["X"].max(), train["Y"].max()

X_outliers = (train["X"] == train["X"].max())
Y_outliers = (train["Y"] == train["Y"].max())
outlier = train[X_outliers & Y_outliers]

non_outliers = train[~(X_outliers&Y_outliers)]

sns.lmplot(data=non_outliers, x="X", y="Y", fit_reg=False)

X,Y좌표를 시각화했기 때문에 실제 땅 모양과 비슷한 모습이 시각화될 거라고 예상했으나 왠걸?

왼쪽과 같이 출력되었고, 이는 outlier 때문이었다.

outlier 제거를 하고 확인하니 예상과 비슷하게 시각화결과가 나온 것을 알 수 있다.

 

 

 3  DayOfWeek

plt.figure(figsize = (12, 4))
dayofweek_list = ["Monday", "Tuesday", "Wednesday", "Thrusday", "Friday", "Saturday", "Sunday"]
sns.countplot(data = train, x = "DayOfWeek", order = dayofweek_list)

figure, axes = plt.subplots(nrows = 10, ncols = 4)
figure.set_size_inches(30, 48)

category_list = train["Category"].value_counts().index

for row in range(10):
    for column in range(4):
        index = row * 4 + column

        if index < len(category_list):
            ax = axes[row][column]
            category = category_list[index]

            target = train[train["Category"] == category]
            sns.countplot(data = target, x = "DayOfWeek", order = dayofweek_list, ax = ax)

            ax.set(xlabel = category)

위의 결과로는 큰 차이가 보이지 않는다.

이는 발생하는 모든 종류의 범죄를 합친 상태이므로, 범죄별로 요일별 발생 비율을 확인해본다.

 

 

범죄별로 나눠서 요일별 발생수를 확인하니 주말에 많이 발생하는 범죄가 있고, 주중에 많이 발생하는 범죄가 있다.
주말을 금토로 하느냐, 토일로 하느냐에 따라서 그 분류가 달라진다.
주중에는 전체적으로 발생수가 많은지, 특정 요일에 많은지에 따라서도 그 분류가 달라진다.
분류에 따라 가중치를 줄 수 있는 컬럼을 추가 생성하면 모델이 더욱 개선된다.

 

 

 4  PdDistrict

figure, axes = plt.subplots(nrows = 10, ncols = 4)
figure.set_size_inches(30, 48)

category_list = train["Category"].value_counts().index

for row in range(10):
    for column in range(4):
        index = row * 4 + column

        if index < len(category_list):
            ax = axes[row][column]
            category = category_list[index]

            target = train[train["Category"] == category]
            sns.countplot(data = target, x = "PdDistrict", ax = ax)

            ax.set(xlabel = category)

DayOfWeek에서처럼 각 범죄마다 관할경찰서별 범죄발생수를 확인했는데,

관할경찰서마다 발생빈도가 높은 범죄종류가 명확하게 나오는 곳이 많다. 그래서 단순히 One Hot Encoding해서 넣어줘도 효과가 좋을 것이다.

 

 

 5  Address

train["Crossroad"] = train["Address"].str.contains("/")
sns.countplot(data=train, x="Crossroad")

plt.figure(figsize = (18, 64))
sns.countplot(data=train, hue="Crossroad", y="Category")

특정 도로에 집중적으로 발생하는 범죄를 알 수 있다.

교차점(Crossroad)과 그렇지 않은 부분(Block)이 특정 범죄에 따라 발생빈도의 차이가 있다.

 

 

 

▶다음글 : 분석

 

반응형