이번 포스팅에서는 인덱스 반복자(iterator) enumerate() 와 numpy 의 다차원 배열에 대한 인덱스 반복자 (multidimensional index iterator) np.ndenumerate(arr) 메소드에 대해서 소개하겠습니다. 

 

(1) 인덱스 반복자 (index iterator): enumerate()

(2) 다차원 배열 (multidimensional index iterator): numpy.ndenumerate(arr)

 

 

 

반복(iteration) 이란 일련의 작업 명령문을 반복해서 실행(repeated execution)하는 것을 말합니다. Python은 이러한 반복 작업을 더 쉽게 수행할 수 있도록 하는 여러 언어 기능이 있습니다.

 

반복자(iterator)는 반복할 수 있는 값의 수를 계산하는 객체입니다. Python의 데이터 유형 중에서 리스트(Lists), 튜플(Tuples), 사전형(Dictionaries), 문자열(Strings), 집합(Sets) 이 모두 반복 가능한 객체들로서, 반복자(iterator)를 가져올 수 있습니다. 

 

 

 

(1) 인덱스 반복자 (index iterator): enumerate()

 

Python에서는 for loop 순환문이 종종 반복가능한 객체에 순환 반복문으로 사용이 됩니다. for loop 문을 사용하면 인덱스 또는 순환하는 횟수는 반환하지 않고, 오로지 반복가능한 객체의 원소만을 반환하게 됩니다.

 

아래 예에서는 리스트(list)에 for loop 문을 사용해서 리스트 안의 원소를 하나씩 순서대로 반복해서 프린트하는 코드입니다. (이때 인덱스 정보는 없음)  

 

## (1) without index iterator
x_list = ['a', 'b', 'c', 'd']

for x in x_list:
    print('item:', x)
    
# item: a
# item: b
# item: c
# item: d

 

 

 

만약 for loop 순환문을 반복가능한 객체에 사용하면서 enumerate() 메소드를 사용하면 쉽고 편리하게 인덱스 정보 (index information)을 같이 반환할 수 있습니다.

 

아래 예에서는 enumerate(x_list) 를 for loop 순환문과 같이 사용해서 '인덱스 정보(index information) + 리스트 내 원소 정보'를 순환하면서 반복적으로 프린트해보았습니다. 

 

## (2) enumerate()
## : iteration with access to the index information
x_list = ['a', 'b', 'c', 'd']
print(x_list)

print('----' * 5)

for i, x in enumerate(x_list):
    print('index:', i, '  item:', x)
    

# ['a', 'b', 'c', 'd']
# --------------------
# index: 0   item: a
# index: 1   item: b
# index: 2   item: c
# index: 3   item: d

 

 

 

(2) 다차원 배열 (multidimensional index iterator): numpy.ndenumerate(arr)

 

numpy 의 다차원 배열 (multidimensional array)에 대해서 위의 (1) enumerate() 메소드가 했던 것처럼 반복 가능한 객체에 대해 인덱스 정보를 가져오고 싶다면 numpy.ndenumerate(arr) 메소드를 사용하면 됩니다. 

 

아래 예에서는 3차원 배열(3 dimensional array) 에 대해서 for loop 순환문과 np.ndenumerate(arr) 메소드를 같이 사용해서 3차원 배열의 인덱스 정보 (index information of 3 dimensional array) 와 원소를 순환하면서 반복적으로 프린트해보았습니다. 

 

## numpy.ndenumerate(arr)
## : multidimensional index iterator

import numpy as np

y_3d_arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(y_3d_arr)

print('------' * 5)

for i, y in np.ndenumerate(y_3d_arr):
    print('index:', i, '  item:', y)
    
# [[[1 2]
#   [3 4]]

#  [[5 6]
#   [7 8]]]
# ------------------------------
# index: (0, 0, 0)   item: 1
# index: (0, 0, 1)   item: 2
# index: (0, 1, 0)   item: 3
# index: (0, 1, 1)   item: 4
# index: (1, 0, 0)   item: 5
# index: (1, 0, 1)   item: 6
# index: (1, 1, 0)   item: 7
# index: (1, 1, 1)   item: 8

 

 

반복 가능한 객체로 리스트(Lists), 튜플(Tuples), 사전형(Dictionaries), 문자열(Strings), 집합(Sets) 등이 있다고 했는데요, 아래 예에서는 다차원 리스트에 대해서 for loop 순환문과 np.ndenumerate() 메소드를 같이 사용해서 인덱스 정보와 리스트 내 원소를 순환하면서 반복적으로 인쇄를 해보았습니다. 

 

## iterable objects: Lists, Tuples, Dictionaries, Strings, Sets

x_2d_list = [['a', 'b'], ['c', 'd']]
print(x_2d_list)

print('-----' * 5)

for i, x in np.ndenumerate(x_2d_list):
    print('index:', i, '  item:', x)
    
# [['a', 'b'], ['c', 'd']]
# -------------------------
# index: (0, 0)   item: a
# index: (0, 1)   item: b
# index: (1, 0)   item: c
# index: (1, 1)   item: d

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다 .

행복한 데이터 과학자 되세요. :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Jupyter Notebook 의 기본 사용법 중에서 

 

(1) Jupyter Notebook Cell 의 모든 결과 지우기 

    : Cell >> All Output >> Clear

(2) Jupyter Notebook 커널 새로 시작하고, 모든 Cell 실행하기

    : Kernel >> Restart & Run All

 

방법에 대해서 소개하겠습니다. 

 

 

(1) Jupyter Notebook Cell 의 모든 결과 지우기

    : Cell >> All Output >> Clear

 

 

아래에 예제로 사용할 간단한 Jupyter Notebook 을 만들어보았습니다.

x, y 객체를 프린트도 해보고, 선 그래프도 그려보았습니다.  

Jupyter Notebook Cell's Results

 

 

이제 Cell >> All Output >> Clear 순서로 메뉴를 선택해서 Cell의 모든 결과를 지워보겠습니다. 

(Clear the output of all cells in Jupyter Notebook) 

 

Jupyter Notebook - Cell - All Output - Clear

 

 

Cell >> All Output >> Clear 의 순서대로 메뉴를 선택해서 실행하면 아래처럼 Cell 의 결과가 모두 지워져서 깨끗해졌습니다. 

Jupyter Notebook - Cleared All Outputs in Cells

 

 

 

(2) Jupyter Notebook 커널 새로 시작하고, 모든 Cell 실행하기

    : Kernel >> Restart & Run All

 

위의 (1)번과는 반대로, 이번에는 Kernel 을 새로 시작(Kernel Restart)하고 모든 Cell을 새로 실행(Run All)해보겠습니다. 

(Kernel >> Restart & Run All)

Jupyter Notebook - Restart & Run All

 

 

아래와 같은 팝업 창이 뜨면 "Restart and Run All Cells" 메뉴를 선택해서 클릭해주면 됩니다. 

 

Jupyter Notebook - Restart and Run All Cells

 

 

그러면, 아래처럼 커널이 새로 시작하고, 모든 셀이 순서대로 다시 실행이 됩니다. 

Jupyter Notebook - Restart and Run All Cells - Results

 

 

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요. 

 

728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 불균형 데이터(imbalanced data)가 무엇이고, 분류 모델링 시 무엇이 문제인지에 대해서 알아보았습니다. --> https://rfriend.tistory.com/773

이번 포스팅부터는 불균형 데이터를 가지고 분류 모델링 시 대처방법에 대해서 몇 번에 나누어서 이론과 Python을 활용한 코드를 소개하겠습니다.  먼저 (3-1) 소수 클래스의 데이터 추가 수집과 (3-2) 불균형 데이터 분류 모델에 적합한 성능평가 지표 선정 부터 시작해볼까요? 

 


[ 불균형 데이터로 분류 모델링하는 방법 ]
  1. 소수 클래스의 데이터 추가 수집 (Get more minority data) 
  2. 불균형 데이터 분류 모델에 적합한 성능평가 지표 선정 
       (evaluation metrics for imbalanced classification)  

  3. 샘플링 방법 (Sampling methods)
    3-1. Undersampling
      : Random Sampling, Tomek Links
    3-2. Oversampling
      : Resampling, SMOTE, Borderline SMOTE, ADASYN
  4. 비용 또는 가중치 조정 방법 (Cost, Weight)
  5. Outlier detection 방법
      : One-class SVM, Isolation Forest, DBSCAN clustering
  6. 확률 튜닝 알고리즘 (Probability Tuning Algorithms)



1. 소수 클래스의 데이터 추가 수집 (Get more minority data)

만약 소수 집단의 데이터를 추가로 수집하거나 또는 생성할 수 있다면 두 집단의 구성비가 균형을 잡히도록 소수 집단의 개수를 늘리면 되겠습니다. 

하지만, 데이터를 수집하는데는 시간과 비용 (time and cost) 이 소요된다는 점, 상황에 따라서는 소수 데이터의 추가 수집이 불가능하다는 점도 고려를 해야겠습니다. 이런 제약사항 때문에 알고리즘적으로 불균형 데이터 문제를 해결하는 방법을 알아둘 필요가 있습니다. 
(다음번 포스팅부터 소개해요)

 

 

 

2. 불균형 데이터 분류 모델에 적합한 성능평가 지표 선정 
     (evaluation metrics for imbalanced classification)

 

균형 데이터 (balanced data)에 대한 
 - 분류 모델의 성능 평가 지표에 대한 이론은 https://rfriend.tistory.com/771 를 참고하구요, 
 - Python 을 이용한 분류 모델의 성능 평가 코드는 https://rfriend.tistory.com/772 를 참고하세요. 

불균형 데이터 (imbalanced data)에 대한 분류 모델 평가 지표를 선정하는 데는 
 (a) 범주와 확률 중에서 무엇을 예측하는가? 
 (b) 두 범주가 동등하게 중요한가? 아니면 양성(Positive) 범주가 더 중요한가?
 (c) False Negative, False Positive 가 동등하게 중요한가? 아니면 둘 중 하나가 더 중요한가?
의 질문에 대한 답변 별로 평가 지표가 달라집니다. 
(아래의 ‘불균형 데이터에 대한 이진 분류 모델 평가 지표’ 참조) 

Performance Metrics of Binary Classification for Imbalanced Data

 

 

 

(1) 범주(class labels)를 예측하고, 두 범주가 동등하게 중요하며, 다수 범주가 80~90% 이상으로서 불균형 데이터(imbalanced data)인 경우 

       --> Geometirc-Mean (or G-Mean) 

G-Mean = sqrt(Sensitivity x Specificity)

 

기하평균 G-Mean 은 다수 집단 (Majority class)과 소수 집단 (Minority class) 간 모두의 분류 성능을 측정하는 지표입니다. 낮은 G-Mean 점수는 비록 음성 사례(negative cases)가 정확하게 분류가 되더라도 양성 사례(positive cases)의 분류는 저조한 성능을 보인다는 뜻입니다. G-Mean 지표는 음성 범주(negative class)의 과적합(over-fitting)을 피하고, 양성 범주(positive class)의 과소 적합(under-fitting)을 피하는데 중요하게 사용됩니다. 

 

(2) 범주를 예측하고, 두 범주가 동등하게 중요하며, 다수 범주가 80~90% 미만인 균형 데이터(balanced data)는

      --> 정확도(Accuracy) 평가지표를 사용하면 됩니다.

하지만, 불균형 데이터에 대해서 정확도 지표를 사용할 경우 다수 집단 만을 잘 분류하고 소수 집단에 대해서는 제대로 분류를 못해도 높은 정확도 점수가 나오는 문제가 있습니다. 

 

 

confusion matrix and performance metrics for the binary classification model
Geometric Mean, G-Mean

 

 

 

(3) 범주 (class labels) 를 예측하고, 양성 범주 (Positive class)가 더 중요하며, 

      - False Negative, False Positve 가 동등하게 중요하면 (Sensitivity, Precision이 균형있으면 좋은 모델)   
         --> F1 Score

      - False Negative 가 더 비용이 크면 (Sensitivity가 높으면 좋은 모델)   --> F2 Score

      - False Positive 가 더 비용이 크면  (Precision이 높으면 좋은 모델)       --> F0.5 Score

를 사용합니다. 

 

 

F1 Score, F0.5 Score, F2 Score 는 높으면 높을수록 더 좋은 모델로 해석합니다.  

참고로, 두 개의 범주가 바뀌어서 양성(Positive)이 음성(Negative)으로, 음성은 양성으로 바뀐 상태에서 혼돈 매트릭스를 만들어서 F2 Score를 계산하면 Inv F0.5 Score 가 됩니다. [2]

 

F-Measures: F1 score, F0.4 score, F2 score, F_beta score

 

 

아래는 불균형 데이터에 대한 분류 모델의 혼돈 매트릭스를 3가지 시나리오 별로 가상으로 구성하여, 민감도(Sensitivity), 정밀도(Precision), F1 Score, F0.5 Score, F2 Score 를 계산해본 것입니다. 위 설명을 이해하는데 도움이 되기를 바랍니다. 

 

 

(a) F1 Score는 정밀도(Precision)와 민감도(Sensitivity) 의 역수의 산술평균의 역수인 조화평균(Harmonic Mean)으로서, 정밀도와 민감도 간의 균형을 측정합니다. 만약 정밀도나 민감도가 0 이라면 F-Measure 는 0 이됩니다. F1 Score는 False Negative 와 False Positive가 동등하게 중요할 때의 모델 성능지표로 적합합니다. 민감도(Sensitivity)와 정밀도(Precision)이 균형있을 때 F1 Score가 높게 나옵니다. 

 

False Negative와 False Positive 가 동등하게 중요한 경우

 

 

(b) 불균형 데이터 (imbalanced data)인 경우에는 F0.5 Score 또는 F2 Score 를 사용하는데요, 비즈니스적으로 중요한 소수 범주(minority class)의 False Negative 가 더 비용(cost)이 크면(즉, Sensitivity가 높은 모델이 더 좋은 모델로서, Sensitiviey에 가중치를 더 줌) F2 Score 를 사용합니다. 예측된 양성이 비록 틀리는 비용을 감수하고서라도, 실제 양성(Positive)을 하나라도 더 분류해내고 싶을 때 F2 Score 지표를 사용합니다. 

 

False Negative 가 더 비용이 큰 경우

 

 

 

(c) 반대로, False Positive 가 비용이 더 크면(즉, (Precision이 높은 모델이 더 좋은 모델로서, Precision에 가중치를 더 줌) F0.5 Score를 모델 성능지표를 선택합니다. 실제 양성을 놓치는 비용을 감수하고서라도, 일단 모델이 양성으로 분류를 했으면 실제로도 양성이기를 바라는 경우에 F0.5 Score 지표를 사용합니다. 

 

False Positive 가 더 비용이 큰 경우

 

 

 

(4) 확률(Probability)을 예측하고, 확률 예측치의 정확도를 평가하고 싶을 때

      --> Brier Score

 

Brier Score 는 확률 예측치의 정확도(accuracy of probability forecast)를 평가할 때 사용합니다. Brier Score 는 두개의 범주(bianry categories)를 가진 이진 분류(binary classification)의 예측 확률에만 사용할 수 모델 평가지표 입니다. [3]

Brier Score의 수식은 아래와 같이 모든 관측치에 대해서 예측확률과 실제 결과(발생하면 1, 아니면 0)와의 차이의 제곱합(Squared Summation)을 관측치의 개수로 나누어서 구한 ‘평균 제곱합 확률 오차(MSE, Mean Squared Error)’ 입니다. 

 

Brier Score

 


Brier Score 는 작으면 작을 수록 이진 분류 모델의 확률 예측치가 정확하다는 뜻이며, 반대로 크면 클 수록 이진 분류 모델의 확률 예측치가 부정확하다고 해석합니다. 

- 모든 확률 예측치에 대해서 완벽하게 모두 다 맞추면 Brier Score 는 0 이 됩니다. (최소값) 
- 반대로, 모든 확률 예측치가 완벽하게 다 틀리면 Brier Score 는 1 이 됩니다. (최대값) 

 

 

 

(5) 확률을 예측하고, 범주가 필요하며, 양성(Positive) 범주가 더 중요한 불균형 데이터의 경우 
   —> Precision-Recall Curve Plot, Precision-Recall AUC (Area Under the Curve)


Precision-Recall Curve 그림은 X축이 Recall, Y축이 Precision으로 해서, 두 범주를 분류하는 확률의 의사결정 기준점(Decision Treshold)을 0에서 1로 조금씩 변경해가면서 혼돈 매트릭스를 계산하고, 이어서 Precision과 Recall을 계산한 후에, 이 값들을 선으로 연결한 그래프입니다. 


아래의 그래프처럼 Precision-Recall Curve 가 우측 상단으로 붙을 수록 불균형 데이터의 양성(Positive)을 더 잘 분류하는 모델이라고 평가할 수 있습니다. (Precision 과 Recall 은 Trade-off 관계에 있음). 

 

Precision-Recall Curve Plot

 


ROC AUC 처럼, Precision-Recall Curve 의 아래 부분의 면적을 적분한 값이 PR AUC (Precision-Recall Area Under the Curve) 값이 됩니다. 하나의 score 로 계산이 되므로, 여러 모델을 수치적으로 비교할 수 있습니다. PR AUC가 크면 클 수록 소수의 양성 범주(minority Positive class) 를 잘 분류하는 모델이라고 평가할 수 있습니다. 

 

PR AUC (Precision-Recall Area Under the Curve)

 

 

 

[ Reference ] 

(1) Tour of Evaluation Metrics for Imbalanced Classification
: https://machinelearningmastery.com/tour-of-evaluation-metrics-for-imbalanced-classification/

(2) "F-score" from Wikipedia: https://en.wikipedia.org/wiki/F-score

(3) Brier Score: https://www.statisticshowto.com/brier-score/

 

728x90
반응형
Posted by Rfriend
,

앞으로 몇 번의 포스팅으로 나누어서 불균형 데이터 (imbalanced data)에 대해서 다루어보도록 하겠습니다. 

 

1. 불균형 데이터 (Imbalanced Data) 란 무엇인가? 
2. 불균형 데이터는 분류 모델링 시 무엇이 문제인가? 
3. 불균형 데이터로 분류 모델링하는 방법에는 무엇이 있나? 


1. 불균형 데이터 (Imbalanced Data) 란 무엇인가? 


불균형 데이터 (Imbalanced Data) 는 목표 변수(target/output variable) 가 범주형 데이터 일 때, 범주 별로 관측치의 개수, 비율의 차이가 많이 나는 데이터를 말합니다. 


아래의 각 산업별 예처럼, 정상 대 비정상의 비율이 90%:10% 처럼 불균형하거나, 더 심하면 99%:1% 처럼 극심하게 불균형한 데이터 (extremely imbalanced data) 도 있습니다. 우리가 관심있어하고 예측하고 싶어하는 비정상 관측치가 정상보다 매우 적은 불균형 데이터를 실무에서는 어렵지 않게 볼 수 있습니다. 

  - 제조회사에서 양품 대 불량품
  - 신용카드회사에서 정상 거래 대 사기 거래 (Fraud) 
  - 은행의 정상 거래 대 돈세탁 거래
  - 의료검진센터에서 정상 대 암(cancer) 진단
  - 사이버보안 회사에서 정상 IP 대 비정상 IP 
  - 통신회사에서 유지 고객 대 이탈(Churn) 고객 
  - 설비/장비의 정상 대 이상 운영
  - 유통회사 대리점의 정상 대 비정상 거래

 


불균형 데이터에서 다수를 차지하는 범주를 ‘다수 범주(majority class)’라고 하고, 적은 수를 차지하는 범주는 ‘소수 범주 (minority class)’ 라고 합니다. 

 

 

 

 

2. 불균형 데이터는 분류 모델링 (Classification Modeling) 시 무엇이 문제인가? 

 


불균형 데이터를 가지고 분류 모델을 훈련시키면 우리가 관심있어하는 minority class 를 제대로 분류할 수 없는 쓸모없는 모델이 만들어질 위험이 있습니다. 가령, 정상(majority class) : 비정상(minority class) 의 비율이 99% : 1% 라고 해보겠습니다. 이런 불균형 데이터에 대해 분류 모델을 훈련시킨 후 예측을 하면 모든 데이터를 ‘정상(majority class)’ 이라고 분류한다고 했을 때 정확도(accuracy)는 99%가 됩니다. 얼필 보면 잘 만들어진 모델 같습니다만, 우리가 관심있어하는 ‘비정상(minority class)’ 범주는 하나도 제대로 분류를 해내지 못했으므로 쓸모없는 모델이라고 하는 것입니다. 

또한, 소수 집단(minority class) 의 관측치 개수가 적으면 소수 집단의 모집단 분포를 샘플링한 소수의 관측치가 대표하기에는 부족하므로 분류 모델이 과적합 (overfitting)에 빠질 위험이 있습니다. 그래서 훈련 데이터셋에는 소수 집단을 분류했다고 하더라도, 새로운 데이터에 대해서는 소수 집단을 제대로 분류를 못할 위험이 있습니다. 

 



3. 불균형 데이터로 분류 모델링하는 방법에는 무엇이 있나? 

 

아래의 6가지 방법이 있는데요, 3-2번 부터 해서 하나씩 차근차근 이어서 포스팅을 해보겠습니다. 

  3-1. 소수 클래스의 데이터 추가 수집 (Get more minority data) 
  3-2. 불균형 데이터 분류 모델에 적합한 성능평가 지표 선정 
       (evaluation metrics for imbalanced classification)
  3-3. 샘플링 방법 (Sampling methods)
    3-3-1. Undersampling
      : Random Sampling, Tomek Links
    3-3-2. Oversampling
      : Resampling, SMOTE, Borderline SMOTE, ADASYN
  3-4. 비용 또는 가중치 조정 방법 (Cost, Weight)
  3-5. Outlier detection 방법
      : One-class SVM, Isolation Forest, DBSCAN clustering
  3-6. 확률 튜닝 알고리즘 (Probability Tuning Algorithms)

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!   :-)

 

728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 분류 모델(classification model)의 성능을 평가할 수 있는 지표 (evaluation metrics)에 대해서 소개하였습니다. (https://rfriend.tistory.com/771)

 

이번 포스팅에서는 Python을 사용하여 예제 데이터에 대해 분류 모델의 성능 평가를 해보겠습니다. 

 

(1) 예제로 사용할 Breast Cancer 데이터셋을 로딩하고, Data와 Target으로 구분

(2) Training set, Test set 분할

(3) Logistic Regression 모델 적합 (Training)

(4) 예측 (Prediction)

(5) 혼돈 매트릭스 (Confusion Matrix)

(6) 분류 모델 성능 지표: Accuracy, Precision, Recall rate, Specificity, F-1 score

(7) ROC 곡선, AUC 점수

 

 

 

(1) 예제로 사용할 Breast Cancer 데이터셋을 로딩하고, Data와 Target으로 구분 

 

target의 '0' 이 'malignant (악성 종양)' 이고, '1'은 'benign' 으로서 정상을 의미합니다. 우리는 'malignant (악성 종양)' 을 분류하는 모델에 관심이 있으므로 target '0' 이 'Positive Label' 이 되겠습니다. 

 

import numpy as np

## load a Iris dataset
from sklearn.datasets import load_breast_cancer

bc = load_breast_cancer()

## target names
bc.target_names
#array(['malignant', 'benign'], dtype='<U9')

## [0: 'malignant'(악성), 1: 'benign']
np.unique(bc['target'], return_counts=True) 
#(array([0, 1]), array([212, 357]))


## getting data, target
bc_data = bc['data']
bc_target = bc['target']

bc_data.shape
#(569, 30)

bc_target[:20]
#array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])

 

 

(2) Training set, Test set 분할

 

Training set 0.5, Test set 0.5 의 비율로 무작위 추출하여 분할하였습니다. 

 

## splits training and test set
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    bc_data, 
    bc_target, 
    test_size=0.5,  
    random_state=1004
)

 

 

 

(3) Logistic Regression 모델 적합 (Training)

 

Traning set을 사용해서 로지스틱 회귀모형을 적합하였습니다.

 

## training a Logistic Regression model with training set
from sklearn.linear_model import LogisticRegression

clf = LogisticRegression(
    solver='liblinear', 
    random_state=1004).fit(X_train, y_train)

 

 

 

(4) 예측 (Prediction)

 

Test set에 대해서 예측을 하고 모델 성능 평가를 해보겠습니다. 

predict() 메소드는 범주를 예측하여 반환하고, predict_praba() 메소드는 확률(probability)을 반환합니다. 

 

## prediction for test set
y_pred = clf.predict(X_test) # class
y_pred_proba = clf.predict_proba(X_test) # probability

 

 

실제 범주의 값과 예측한 범주의 값, 그리고 target '0'(malignant, 악성 종양) 일 확률을 DataFrame으로 묶어보았습니다. 

 

# All in a DataFrame
pred_df = pd.DataFrame({
    'actual_class': y_test, 
    'predicted_class': y_pred, 
    'probabilty_class_0': y_pred_proba[:,0] # malignant (악성)
})

pred_df.head(10)
#    actual_class  predicted_class  probabilty_class_0
# 0             1                1            0.002951
# 1             0                0            0.993887
# 2             0                1            0.108006
# 3             1                1            0.041777
# 4             0                0            1.000000
# 5             0                0            1.000000
# 6             0                0            0.999633
# 7             1                1            0.026465
# 8             0                0            0.997405
# 9             1                1            0.002372

 

 

 

이제 여기서부터 분류 모델의 성능 평가를 시작합니다. 

 

(5) 혼돈 매트릭스 (Confusion Matrix)

 

혼돈 매트릭스의 Y축은 Actual 의 malignant (0), benign(1) 이며, X 축은 Predicted 의 malignant (0), benign(1) 입니다. 

 

## model evaluation
# Confusion matrix
from sklearn.metrics import confusion_matrix

confusion_matrix(y_test, y_pred, 
                 labels=[0, 1]) # 'malignant'(0), 'benign'(1)

#                   predicted
#                   malignant  benign
# actual malignant [[102,       16],
#        benign    [  3,       164]])

 

confusion matrix

 

 

 

(6) 분류 모델 성능 지표: Accuracy, Precision, Recall rate, Specificity, F-1 score

 

from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_recall_fscore_support

## performance metrics
accuracy = accuracy_score(y_test, y_pred)

precision, recall, fscore, support = \
    precision_recall_fscore_support(y_test, y_pred)

print('Accuracy   : %.3f' %accuracy) # (102+164)/(102+16+3+164)
print('Precision  : %.3f' %precision[0]) # 102/(102+3)
print('Recall     : %.3f' %recall[0]) # 102/(102+16)
print('Specificyty: %.3f' %recall[1]) # 164/(3+164)
print('F1-Score   : %.3f' %fscore[0]) # 2/(1/precision + 1/recall) = 2/(1/0.971+1/0.864)

# Accuracy   : 0.933
# Precision  : 0.971
# Recall     : 0.864
# Specificyty: 0.982
# F1-Score   : 0.915

 

 

sklearn의 classification_report() 메소드를 활용해서 한꺼번에 쉽게 위의 분류 모델 성능평가 지표를 계산하고 출력할 수 있습니다. 참고로, 'macro avg' 는 가중치가 없는 평균이며, 'weighted avg'는 support (관측치 개수) 로 가중치를 부여한 평균입니다. 

 

from sklearn.metrics import classification_report

target_names = ['malignant(0)', 'benign(1)']
print(classification_report(y_test, y_pred, 
                            target_names=target_names))

#               precision    recall  f1-score   support

# malignant(0)       0.97      0.86      0.91       118
#    benign(1)       0.91      0.98      0.95       167

#     accuracy                           0.93       285
#    macro avg       0.94      0.92      0.93       285
# weighted avg       0.94      0.93      0.93       285

 

 

 

 

(7) ROC 곡선, AUC 점수

 

ROC 곡선과 AUC 점수는 예측 확률을 이용합니다.

ROC 곡선은 모든 의사결정 기준선 (decision threshold)에 대하여 혼돈 매트릭스를 만들고, X축에는 False Positive Rate(=1-specificity), Y축에는 True Positive Rate (=recall, sensitivity) 의 값을 선그래프로 그린 것이며, 좌측 상단으로 그래프가 붙을 수록 더 잘 적합된 모델이라고 평가합니다. AUC 점수는 ROC 곡선의 아랫부분의 면적을 적분한 값입니다. 

 

## ROC Curve, AUC
import sklearn.metrics as metrics

fpr, tpr, threshold = metrics.roc_curve(
    y_test, 
    y_pred_proba[:, 0], 
    pos_label=0) # positive label

AUC = metrics.auc(fpr, tpr)

 

 

# plotting ROC Curve
import matplotlib.pyplot as plt

plt.figure(figsize = (8, 8))
plt.plot(fpr, tpr, 'b', label = 'AUC = %0.3f' % AUC)
plt.title(('ROC Curve of Logistic Regression'), fontsize=18)
plt.legend(loc = 'lower right')

plt.plot([0, 1], [0, 1],'r--') # random guess
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate', 
                fontsize=14)
plt.xlabel('False Positive Rate', 
                fontsize=14)

plt.show()

ROC curve, AUC score

 

 

[ Reference ] 

1) Breast Cancer Dataset
: https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_breast_cancer.html

2) Scikit-Learn Logistic Regression
: https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html

3) 분류 모델의 성과 평가 지표 : https://rfriend.tistory.com/771

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 분류 모델 (classification model) 의 성능을 비교 평가할 수 있는 지표(evaluation metrics)들에 대해서 소개하겠습니다. 

 

(1) 혼돈 매트릭스 (Confusion Matrix)

(2) 혼돈 매트릭스 기반 분류 모델 성능 평가 지표

    - 정확도 (Accuracy)

    - 재현율 (Recall rate), 민감도 (Sensitivity)

    - 특이도 (Specificity)

    - 정밀도 (Precision)

    - F-1 점수 (F-1 Score)

(3) 정밀도와 재현율의 상충 관계 (Precision/ Recall Trade-off)

(4) 분류 확률 기반 ROC Curve, AUC (Area Under the ROC Curve)

(5) Python 을 이용한 분류 모델 성능 평가 (다음번 포스팅)

 

 

 

(1) 혼돈 매트릭스 (Confusion Matrix)

 

먼저 범주의 정답(Y, Label)을 알고 있는 데이터의 실제 값 (Actual) 과 분류 모델을 통해 분류한 예측 값 (Predicted) 을 평가하여 아래와 같은 표의 형태로 객체의 수를 셉니다. Positive 는 '1'/ 'Success'/ 'Pass'/ 'Live' 등에 해당하며, Negative 는 '0'/ 'Fail'/ 'Non Pass'/ 'Dead' 등을 의미합니다. 

 

TP (True Positive), FP (False Positive), FN (False Negative), TN (True Negative) 는 아래의 표를 보면 의미가 더 명확할거예요. (P와 N은 예측치를 의미하며, 이걸 실제 값과 비교했을 때 맞혔으면 True, 틀렸으면 False 로 표기한 것임)

 

책에 따라서 '실제 값 (Actual)'과 '예측 값 (Predicted)' 의 축이 다른 경우도 있으니 가로 축과 세로 축이 무엇을 의미하는지 꼭 확인이 필요합니다. 

 

confusion matrix

 

 

 

(2) 혼돈 매트릭스 기반 분류 모델 성능 평가 지표

 

모든 관측치의 개수를 N (= TP + TN + FP + FN) 이라고 하면, 

 

    - 정확도 (Accuracy) = (TP + TN) / N

    - 재현율 (recall rate), 민감도 (Sensitivity) = TP / (TP + FN)

    - 특이도 (Specificity) = TN / (FP + TN)

    - 정밀도 (Precision) = TP / (TP + FP)

    - F1 점수 (F1 Score) = 1 / (1/Precision + 1/Recall)

 

의 수식을 이용해서 구할 수 있습니다. 

F-1 점수 (F-1 Score)는 정밀도와 재현율의 조화평균(harmonic mean, 역수의 산술평균의 역수)으로서, 정밀도와 재현율이 균형있게 둘 다 높을 때 F-1 점수도 높게 나타납니다. 정밀도와 재현율이 모두 중요한 경우에는 F-1 점수를 사용해서 모델을 평가하면 됩니다. 

 

accuracy, recall rate, sensitivity, specificity, precision, F-1 score

 

 

 

(3) 정밀도와 재현율의 상충 관계 (Precision/ Recall Trade-off)

 

정밀도(Precision)와 재현율(Recall rate)은 분류 예측을 위한 의사결정 기준점(decision threshold)을 얼마로 하느냐에 따라 달라집니다. (의사결정 기준점에 따라 혼돈 매트릭스의 4사분면의 각 숫자가 달라짐) 

정밀도와 재현율은 상충 관계에 있어서, 마치 시소 게임처럼 정밀도가 높아지면 재현율이 낮아지고, 반대로 재현율이 높아지면 정밀도는 낮아집니다. 이 상충관계를 잘 이해해야 왜 이렇게 많은 분류 모델 성과평가 지표가 존재하고 필요한지 이해할 수 있습니다. 

 

보통은 '양성(Positive, 1)' 으로 분류할 확률이 의사결정 기준점 '0.5' 보다 크면 '양성 (Positive, 1)' 로 분류하고, '0.5' 보다 같거나 작으면 '음성 (Negative, 0)' 으로 분류를 합니다. (아래 그림의 (2)번 케이스)

 

만약 '실제 양성' (Actual Positive) 을 더 많이 잡아내고 싶으면 (실제 음성을 양성으로 오분류할 비용을 감수하고서라도), 의사결정 기준점을 내려주면 됩니다. (아래 그림의 (1)번 케이스) 그러면 재현율(Recall rate)은 올라가고, 정밀도(Precision) 은 낮아집니다. 

 

만약 '예측한 양성'이 실제로도 양성인 비율 (즉, 정밀도, Precision)을 높이고 싶으면 의사결정 기준점을 올려주면 됩니다. (아래 그림의 (3)번 케이스). 그러면 정밀도(Precision)은 올라가고, 재현율(Recall rate)은 내려가게 됩니다. 

 

precision/ recall trade-off

 

의사결정 기준점을 변경하고 싶다면 비즈니스 목적 상 재현율과 정밀도 중에서 무엇이 더 중요한 지표인지, 실제 양성을 놓쳤을 때의 비용과 예측한 양성이 실제로는 음성이었을 때의 비용 중에서 무엇이 더 끔찍한 것인지를 생각해보면 됩니다. 

 

가령, 만약 코로나 진단 키트의 분류 모델이라면 '실제 양성 (즉, 코로나 감염)' 인 환자가 '음성'으로 오분류 되어 자가격리 대상에서 제외되고 지역사회에 코로나를 전파하는 비용이 '실제 음성 (즉, 코로나 미감염)' 인 사람을 '양성'으로 오분류했을 때보다 비용이 더 크다고 할 수 있으므로 (1) 번 케이스처럼 의사결정 기준점을 내려서 재현율(Recall rate)을 올리는게 유리합니다. 

 

반면, 유튜브에서 영유아용 컨텐츠 적격 여부를 판단하는 분류모델을 만든다고 했을 때는, 일단 분류모델이 '영유아용 적격 판단 (Positive)' 을 내련 영상 컨텐츠는 성인물/폭력물/욕설 등의 영유아용 부적격 컨텐츠가 절대로 포함되어 있으면 안됩니다. 이럴경우 일부 실제 영유아용 적격 컨텐츠가 '부적격'으로 오분류되는 비용을 감수하고서라도 (3)번 케이스처럼 의사결정 기준점을 올려서 정밀도를 높게 해주는 것이 유리합니다. 

 

그리고, 극도로 불균형한 데이터셋 (extremely imbalanced dataset) 의 경우 정확도(Accuracy) 지표는 모델을 평가하는 지표로 부적절합니다. 이때는 비즈니스 목적에 맞게 재현율과 정밀도 중에서 선택해서 사용하는 것이 필요합니다. (양성이 희소한 경우 모델이 모두 음성이라고 예측해도 정확도 지표는 매우 높게 나옴. 하지만 우리는 희소한 양성을 잘 찾아내는 모델을 원하지 모두가 다 음성이라고 예측하는 쓸모없는 모델을 원하지는 않음.)

 

 

 

(4) 분류 확률 기반 ROC Curve, AUC (Area Under the ROC Curve)

 

ROC 곡선(Receiver Operating Characteristic Curve)은 모든 분류 의사결정 기준값(decision threshold)에서 분류 모델의 성능을 보여주는 그래프입니다. X축은 False Positive Rate, Y축은 True Positive Rate 으로 하여 모든 의사결정 기준값 (Positive 일 확률) 별로 혼돈 매트릭스를 구하고, 여기에서 재현율과 특이도를 구해서 TPR과 FPR을 구하고, 이를 선으로 연결해주면 됩니다. 

 

ROC Curve

 

ROC 곡선은 45도 대각선이 무작위로 추측하여 분류했을 때를 의미하며, ROC 곡선이 좌측 상단으로 붙으면 붙을 수록 분류 모델의 성능이 더 좋다고 해석합니다. (False Positive Rate 보다 True Positive Rate이 상대적으로 더 높을 수록 더 좋은 분류 모델임)

 

 

AUC (Area Under the ROC Curve) 점수는 위의 ROC 곡선의 아랫 부분을 적분하여 하나의 수치로 분류 모델의 성능을 표현한 것입니다. AUC 점수가 높으면 높을 수록 더 좋은 분류 모델입니다.  

 

ROC 곡선과 AUC 모두 분류 모델이 '양성일 확률(probability)'을 반환할 때만 계산이 가능합니다.

(즉, 모델이 분류할 범주(category, class)로 예측값을 반환하면 ROC 곡선, AUC 계산 불가)

 

AUC

 

 

다음번 포스팅에서는 Python을 이용한 분류모델 성능 평가를 해보겠습니다. 

(https://rfriend.tistory.com/772)

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python pandas DataFrmae에서 filter() 함수를 사용하여 특정 조건에 맞는 칼럼이나 행을 선택해서 가져오는 방법을 소개하겠습니다. 

 

(1) pd.DataFrame.filter() 함수의 items 옵션을 사용하여 '이름'으로 행이나 열을 선택해서 가져오기 

(2) pd.DataFrame.filter() 함수의 regex 옵션을 사용하여 '정규 표현식'으로 행이나 열을 선택해서 가져오기

(3) pd.DataFrame.filter() 함수의 like 옵션을 사용하여 '특정 문자를 포함'하는 행이나 열을 선택해서 가져오기

 

 

pandas.DataFrame.filter()

 

 

먼저 예제로 사용할 간단한 DataFrame을 만들어보겠습니다. 

 

## sample pandas DataFrame

import numpy as np
import pandas as pd

df = pd.DataFrame(
    np.arange(12).reshape(3, 4), 
    index=['abc', 'bbb', 'ccc'], 
    columns=['x_1', 'x_2', 'var1', 'var2'])
    

df

#      x_1  x_2  var1  var2
# abc    0    1     2     3
# bbb    4    5     6     7
# ccc    8    9    10    11

 

 

 

(1) pd.DataFrame.filter() 함수의 items 옵션을 사용하여 '이름'으로 행이나 열을 선택해서 가져오기

 

(1-1) pd.DataFrame.filter(items = ['칼럼 이름 1', '칼럼 이름 2', ...], axis=1) 옵션을 사용해서 '특정 칼럼 이름'의 데이터를 선택해서 가져올 수 있습니다. 칼럼 이름은 리스트 형태 (list-like) 로 나열해줍니다. axis 의 디폴트 옵션은 axis = 1 로서 칼럼 기준입니다. 

참고로, 일상적으로 많이 사용하는 df[['칼럼 이름 1', '칼럼 이름 2', ...]] 와 같습니다.  

 

## pd.DataFrame.filter()
## : Subset the dataframe rows or columns according to the specified index labels.
## reference: https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html

## (1-1) items: select columns by name
## equivalently: df[['x_1', 'var2']]
df.filter(items=['x_1', 'var2'], axis=1)

#      x_1  var2
# abc    0     3
# bbb    4     7
# ccc    8    11

 

 

 

(1-2) pd.DataFrame.filter(items = ['열 이름 1', '열 이름 2', ...], axis=0) 옵션을 사용해서 '특정 열 이름'의 데이터를 선택해서 가져올 수 있습니다. 

참고로, 자주 사용하는 df.loc[['열 이름 1', '열 이름 2', ...]] 와 같습니다. 

 

## (1-2) items: select rows by name
## equivalently: df.loc[['bbb', 'abc']]
df.filter(items=['bbb', 'abc'], axis=0)

#      x_1  x_2  var1  var2
# bbb    4    5     6     7
# abc    0    1     2     3

 

 

 

(2) pd.DataFrame.filter() 함수의 regex 옵션을 사용하여 '정규 표현식'으로 행이나 열을 선택해서 가져오기

 

DataFrame.filter() 함수의 힘은 정규 표현식(regular expression)을 사용해서 행이나 열을 선택할 수 있다는 점입니다. 정규 표현식은 너무 광범위해서 이 포스팅에서 세부적으로 다루기에는 무리구요, 아래에는 정규 표현식의 강력함에 대한 맛보기로 세 개의 예시를 준비해봤습니다. 

 

 

(2-1) 정규 표현식을 이용해서 특정 문자로 시작(^)하는 모든 칼럼 선택해서 가져오기: regex='^(특정문자).+'

 

## (2) select columns by regular expression
## (2-1) 'x_' 로 시작하는 모든 칼럼 선택
## 캐럿 기호 ^는 텍스트의 시작, 
df.filter(regex='^(x_).+', axis=1)

#      x_1  x_2
# abc    0    1
# bbb    4    5
# ccc    8    9

 

 

(2-2) 정규 표현식을 이용해서 특정 문자로 끝나는($) 모든 칼럼 선택해서 가져오기: regex='특정문자$'

 

## (2-2) '2' 루 끝나는 모든 칼럼 선택
## 달러 기호 $는 텍스트의 끝
df.filter(regex='2$', axis=1)

#      x_2  var2
# abc    1     3
# bbb    5     7
# ccc    9    11

 

 

(2-3) 정규 표현식을 이용해서 특정 문자로 시작하지 않는 모든 칼럼 선택해서 가져오기: regex='^(?!특정문자).+'

 

## (2-3) 'x_' 로 시작하지 않는 모든 칼럼 선택
df.filter(regex='^(?!x_).+', axis=1)

#      var1  var2
# abc     2     3
# bbb     6     7
# ccc    10    11

 

 

(2-4) 정규 표현식을 이용해서 행 이름의 끝에 특정 문자를 포함하는 행(row)을 선택하기
            : DataFrame.filter(regex='특정문자$', axis=0)

 

## select rows(axis=0) containing 'c' at the end using regular expression.
df.filter(regex='c$', axis=0)

#      x_1  x_2  var1  var2
# abc    0    1     2     3
# ccc    8    9    10    11

 

 

 

(3) pd.DataFrame.filter() 함수의 like 옵션을 사용하여 '특정 문자를 포함'하는 행이나 열을 선택해서 가져오기

 

(3-1) 특정 문자를 포함하는 칼럼(column)을 선택해서 가져오기: df.filter(like='특정 문자', axis=1)

 

## (3) filter(like) 
## select columns(axis=1) containing 'x_'
df.filter(like='x_', axis=1)

#      x_1  x_2
# abc    0    1
# bbb    4    5
# ccc    8    9

 

 

(3-2) 특정 문자를 포함하는 행(row)을 선택해서 가져오기: df.filter(like='문정 문자', axis=0)

 

## select rows(axis=0) containing 'b' in a string
df.filter(like='b', axis=0)

#      x_1  x_2  var1  var2
# abc    0    1     2     3
# bbb    4    5     6     7

 

 

[Reference]

pandas.DataFrame.filter(): https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.filter.html

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 여러개의 칼럼을 가지는 pandas DataFrame에서 특정 데이터 유형의 칼럼을 선택하거나 배제하는 방법을 소개하겠습니다. 

 

(1) pandas DataFrame 의 칼럼별 데이터 유형 확인: df.dtypes

(2) pandas DataFrame 에서 특정 데이터 유형의 칼럼을 선택하기: df.select_dtypes(include)

(3) pandas DataFrame 에서 특정 데이터 유형의 칼럼을 제외하기: df.select_dtypes(exclude)

 

 

pandas.DataFrame.select_dtypes(include, exclude)

 

 

먼저, 예제로 사용할 pandas DataFrame을 만들어보겠습니다. 데이터 유형으로는 int64, object, boolean, folat64, datetime64 의 5개 서로 다른 유형을 포함하도록 하였습니다. 

 

import pandas as pd

## sample pandas DataFrame
df = pd.DataFrame({
    'x1': [1, 2, 3], # int64
    'x2': ['a', 'b', 'c'], # object
    'x3': [True, False, False], # boolean
    'x4': [1.0, 2.0, 3.0], # float64
    'x5': [pd.Timestamp('20230101'), pd.Timestamp('20230102'), pd.Timestamp('20230103')] # datetime64
})


print(df)
#    x1 x2     x3   x4         x5
# 0   1  a   True  1.0 2023-01-01
# 1   2  b  False  2.0 2023-01-02
# 2   3  c  False  3.0 2023-01-03
# 3   4  d   True  4.0 2023-01-04

 

 

 

(1) pandas DataFrame 의 칼럼별 데이터 유형 확인: df.dtypes

 

## (1) pd.DataFrame.dtypes: data type of each column.

df.dtypes
# x1             int64
# x2            object
# x3              bool
# x4           float64
# x5    datetime64[ns]
# dtype: object

 

 

 

(2) pandas DataFrame 에서 특정 데이터 유형의 칼럼을 선택하기 (include)

 

pd.DataFrame.select_dtypes(include=None) 메소드를 사용하여 원하는 데이터 유형을 include = 'data type' 옵션에 넣어주면 됩니다. 아래 예시에서는 차례대로 include='int64', 'object', 'bool', float64', 'datetime64' 별로  칼럼을 선택해보았습니다. 

 

## (2) DataFrame.select_dtypes(include=None, exclude=None)
## Return a subset of the DataFrame’s columns based on the column dtypes.

## including the dtypes in include.
df.select_dtypes(include='int64') # int
# x1
# 0	1
# 1	2
# 2	3
# 3	4


df.select_dtypes(include='object')
# x2
# 0	a
# 1	b
# 2	c
# 3	d


df.select_dtypes(include='bool')
# x3
# 0	True
# 1	False
# 2	False
# 3	True


df.select_dtypes(include='float64') # float
# x4
# 0	1.0
# 1	2.0
# 2	3.0
# 3	4.0


df.select_dtypes(include='datetime64') # datetime
# x5
# 0	2023-01-01
# 1	2023-01-02
# 2	2023-01-03
# 3	2023-01-04

 

 

 

한꺼번에 여러개의 데이터 유형의 칼럼을 선택하고자 할 때는 df.select_dtypes(include=[dtype1, dtype2, ...]) 처럼 include 옵션에 여러개의 데이터 유형을 리스트로 넣어주면 됩니다. 아래 예시에서는 ['int64', 'float64'] 의 두 개의 숫자형 칼럼을 선택해 보았습니다. 

 

숫자형 (numeric data type) 의 칼럼을 선택하는 또 다른 방법은 df.select_dtypes(include='number') 를 해도 됩니다. 

 

## (a) include=[dtype, dtype, ...]
df.select_dtypes(include=['int64', 'float64']) # 여러개의 data type

# x1	x4
# 0	1	1.0
# 1	2	2.0
# 2	3	3.0
# 3	4	4.0



## (b) To select all numeric types, use np.number or 'number'
df.select_dtypes(include='number') # int, float

# x1	x4
# 0	1	1.0
# 1	2	2.0
# 2	3	3.0
# 3	4	4.0

 

 

숫자형('int64', 'float64') 의 칼럼 이름을 리스트로 반환하려면 columns 로 칼럼 이름을 가져와서 list() 로 묶어주면 됩니다. 

 

## column names of numeric types
list(df.select_dtypes(include='number').columns)

# ['x1', 'x4']

 

 

 

(3) pandas DataFrame 에서 특정 데이터 유형의 칼럼을 제외하기 (exclude)

 

위의 (2)번이 특정 데이터 유형을 포함(include)하는 칼럼을 선택하는 것이었다면, 이번에는 특정 데이터 유형을 제외(exclude) 한 나머지 칼럼을 선택하는 방법입니다. 아래 예시에서는 'int64' 데이터 유형을 제외(exclude='int64')한 나머지 칼럼을 반환하였습니다. 

 

## excluding the dtypes in exclude.
df.select_dtypes(exclude='int64')

# x2	x3	x4	x5
# 0	a	True	1.0	2023-01-01
# 1	b	False	2.0	2023-01-02
# 2	c	False	3.0	2023-01-03
# 3	d	True	4.0	2023-01-04

 

 

 

[Reference]

pandas.DataFrame.select_dtypes(include=None, exclude=None)
: https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.select_dtypes.html

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

Python 리스트 자료형의 메소드와 내장함수에 대해서는 https://rfriend.tistory.com/330 를 참고하세요. 

 

이번 포스팅에서는 리스트(List) 자료형에 대한 유용한 활용 팁 네가지를 소개하려고 합니다. 

 

(1) 리스트의 문자형 원소를 숫자형 원소로 바꾸기 (혹은 그 반대)

(2) 리스트의 원소를 사전형의 Key:Value 기준으로 매핑하여 변환하기

(3) 리스트에서 또 다른 리스트의 겹치는 원소를 빼기

(4) 리스트 원소 정렬하기 (내림차순, 오름차순)

 

 

(1) 리스트의 문자형 원소를 숫자형 원소로 바꾸기 (혹은 그 반대)

 

list(map(data type, list)) 으로 리스트 내 원소의 데이터 유형을 변환할 수 있습니다. 아래는 순서대로 리스트 내 문자형 원소를 숫자형으로 변환, 숫자형 원소를 문자형 원소로 변환한 예입니다. 

 

## convert a list with string-type elements into a list with numeric-type elements
list(map(int, ['1', '2', '3']))  # 문자형 원소
# [1, 2, 3] # --> 숫자형으로 변환됨


## convert a list with numeric-type elements into a list with string-type elements
list(map(str, [1, 2, 3]))  # 숫자형 원소
# ['1', '2', '3'] # --> 문자형으로 변환됨

 

 

 

(2) 리스트의 원소를 사전형의 Key:Value 기준으로 매핑하여 변환하기

 

리스트 내 원소를 다른 값으로 변환할 때 사전형(Dictionary)의 Key:Value 매핑을 이용하면 편리합니다. List Comprehension 을 이용해서 리스트 원소별로 for loop 을 돌면서 Dictionary 의 Dict[Key] 로 Value에 접근해서 키별로 값을 매핑해서 변환된 값으로 새로운 리스트를 만들어줍니다

 

converting elements in a list using Dictionary(Key: Value)

 

## a List
my_list = ['c', 'a', 'd', 'b']


## a Dictionary, which will be used for mapping, converting
my_dict = {
    'a': 1, 
    'b': 2, 
    'c': 3, 
    'd': 4
}

## accessing the value in a Dictionary using the key
my_dict['a']
# 1


## converting elements in a list using a Dictionary (Key: Value)
[my_dict[k] for k in my_list]
# [3, 1, 4, 2]

 

 

 

(3) 리스트에서 또 다른 리스트의 겹치는 원소를 빼기

 

리스트와 리스트 간 중복되는 원소 값 빼기는 TypeError: unsupported operand type(s) for -: 'list' and 'list' 에러를 반환합니다. 

 

## sample lists
a = [1, 2, 3, 4, 5]
b = [4, 5, 6, 7, 8]


## TypeError: unsupported operand type(s) for -: 'list' and 'list'
a - b
# ---------------------------------------------------------------------------
# TypeError                                 Traceback (most recent call last)
# <ipython-input-36-4dfa3698e4b8> in <module>
# ----> 1 a- b

# TypeError: unsupported operand type(s) for -: 'list' and 'list'

 

 

리스트 간 겹치는 값을 제거하려면 먼저 리스트를 Set 으로 변환을 해주고, 두 개의 Sets 간에 빼기를 해준 다음에, 집합 간 빼기 가 된 결과를 다시 list() 를 사용해서 리스트로 최종 변환해주면 됩니다. 

 

## substraction between lists using set
list(set(a) - set(b))
# [1, 2, 3]


list(set(b) - set(a))
# [8, 6, 7]

 

 

 

(4) 리스트 원소 정렬하기 (내림차순, 오름차순)

 

list.sort() 메소드를 사용해서 리스트 원소 (숫자형) 를 오름차순으로 정렬할 수 있습니다. 

내림차순 정렬을 하려면 list.sort(reverse=True) 처럼 옵션을 추가해주면 됩니다. 

## 리스트 원소 정렬
c = [8, 6, 7]
c.sort()
c
# [6, 7, 8]



## 리스트 원소 역순으로 정렬
c.sort(reverse=True)
c
# [8, 7, 6]

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python의 Dictionary로 Key: Value 매핑하여 문자열을 변경해주는 replace() 함수를 사용하여 SQL query 코드의 여러개의 문자열을 변경하는 방법을 소개하겠습니다. 

코드가 길고 동일한 특정 변수나 테이블 이름이 여러번 나오는 경우, 수작업으로 일일이 하나씩 찾아가면서 변수나 테이블 이름을 변경하다보면 사람의 실수(human error)가 발생할 위험이 큽니다.  이럴 때 Dictionary에 (변경 전 : 변경 후) 매핑을 관리하고 컴퓨터에게 코드 변경을 시킬 수 있다면 사람의 실수를 예방하는데 도움이 될 것입니다. 

 

먼저, 예제로 사용할 SQL query와 Key(Before, 변경 전): Value(After, 변경 후) 를 매핑한 Dictionary 를 만들어보겠습니다. 

 

## key(Before): value(After) mapping dictionary
map_dict = {
    'X1': '"변수1"', # Key(Before): Value(After)
    'X2': '"변수2"', 
    'X3': '"변수3"',
    'MYTABLE': 'TEST_TABLE'
}


sql_query = "select \nx1, x2, x3 \nfrom mytable \nwhere x2 > 10 \nlimit 10;"

print(sql_query)
# select 
# x1, x2, x3 
# from mytable 
# where x2 > 10 
# limit 10;

 

 

 

아래에는 여러개의 줄(lines)을 가지는 문자열을 하나의 줄(line)로 나누어주는 splitlines() 메소드와, Dictionary의 Key, Value를 쌍으로 반환해주는 items() 메소드를 소개하였습니다. 

 

## splitlines()
for l in sql_query.splitlines():
    print(l)

# select 
# x1, x2, x3 
# from mytable 
# where x2 > 10 
# limit 10;



## replace(a, b) method convert a string 'a' with 'b'
s = 'Hello Python World.'
s.replace('Hello', 'Hi')

# 'Hi Python World.'



# dictionary.items() ==> returns key, value
for k, v in map_dict.items():
    print(k, ':', v)

# X1 : "변수1"
# X2 : "변수2"
# X3 : "변수3"
# MYTABLE : TEST_TABLE

 

 

 

위에서 기본적인 splitlines(), replace(), items() 메소드에 대한 사용법을 알았으니, 이제 이를 엮어서 코드에 있는 여러개의 특정 변수나 테이블 이름을 Dictionary(변경 전 이름 Key: 변경 후 이름 Value 매핑) 에서 가져와서 replace() 메소드로 변경해주는 사용자 정의함수를 만들어보겠습니다. 

 

## User Defined Function for converting codes 
## using replace() function and dictionary(Before: After mapping)
def code_converter(codes_old, map_dict):
    # blank string to save the converted codes
    codes_converted = ''
    
    # converting codes using replace() function and dictionary(Before: After mapping)
    for code in codes_old.splitlines():
        for before, after in map_dict.items():
            code = code.upper().replace(before, after)
            
        codes_converted = codes_converted + code + '\n'
        
    return codes_converted
    

## executing the UDF above
sql_query_new = code_converter(sql_query, map_dict)


print(sql_query_new)
# SELECT 
# "변수1", "변수2", "변수3" 
# FROM TEST_TABLE 
# WHERE "변수2" > 10 
# LIMIT 10;

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,