Post

다양한 데이터 활용법

다양한 데이터 활용법

1. 학습 준비

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 데이터와 라이브러리가 준비 되었다면 아래 코드로 데이터가 잘 불러지는지 확인해보자.
import os 
import pandas as pd 
from pandasql import sqldf
# pandasql을 전역 환경으로 지정
mysql = lambda q: sqldf(q, globals())

data_dir = 'C:/Users/daydr/data/sql_basic/'

bike = pd.read_csv(os.path.join(data_dir, 'bike_dataset.csv'))
orders = pd.read_csv(os.path.join(data_dir, 'orders.csv'))
customers = pd.read_csv(os.path.join(data_dir, 'customers.csv'))
employees = pd.read_csv(os.path.join(data_dir,'employees.csv'))
ds_2020 = pd.read_csv(os.path.join(data_dir, 'DS_JobsSalaries_2020.csv'))
ds_2021 = pd.read_csv(os.path.join(data_dir, 'DS_JobsSalaries_2021.csv'))

print("데이터 준비 완료!")
1
데이터 준비 완료!

2. 특정 데이터 조건과 별칭

2-1. 특정 데이터 조건 주기(LIKE, Wildcard)

LIKE

  • 조회 조건 값이 명확하지 않을 때 특정 내용을 찾을 수 있음.
  • 조건에 문자나 숫자를 포함할 수 있다.
  • 주로 Wildcard와 함께 사용

Wildcard

  • % : 조건을 포함하는 모든 문자를 의미한다. (0개 이상의 문자)
  • _ : 한 글자를 의미한다.
    • _ 의 개수에 따라 뒤에 오는 문자열의 개수를 정할 수 있다.
    • ex. to_ 라고 지정하면 tom은 추출되지만 tomi는 추출되지 않음
1
2
3
4
5
6
7
8
9
10
11
# hr이 0이고, weekday에 'ur'이란 단어가 들어간 데이터를 추출해보자.

mysql("""

SELECT *
FROM bike
WHERE hr = 0
AND weekday LIKE '%ur%'
LIMIT 3;

""")
dtedayseasonyrmnthhrholidayweekdayworkingdayweathersittempatemphumwindspeedcasualregisteredcnt
02011-01-01spring2011Jan00Saturday0Clear0.240.28790.810.000031316
12011-01-06spring2011Jan00Thursday1Clear0.180.24240.550.000001111
22011-01-08spring2011Jan00Saturday0Cloudy0.180.19700.510.164212425
  • weathersit이 ‘Cl’로 시작하는 데이터를 추출해 보자.
    • AND weathersit LIKE 'Cl%'
  • mnth이 ‘ma?’인 데이터를 확인해 보자.
    • AND mnth LIKE 'ma_'
1
2
3
4
5
6
7
8
9
10
11
12
13
# 응용해보자.
# hr이 0이고, mnth이 'ma?'이며 weekday에 'ur'이란 단어가 들어간 데이터를 추출해 보자.

mysql(""" 

SELECT *
FROM bike
WHERE hr = 0
AND mnth LIKE 'ma_'
AND weekday LIKE '%ur%'
LIMIT 5;

""")
dtedayseasonyrmnthhrholidayweekdayworkingdayweathersittempatemphumwindspeedcasualregisteredcnt
02011-03-03spring2011Mar00Thursday1Clear0.240.19700.300.462731013
12011-03-05spring2011Mar00Saturday0Cloudy0.280.28790.810.104541519
22011-03-10spring2011Mar00Thursday1LightRain0.340.31820.000.2537303
32011-03-12spring2011Mar00Saturday0Clear0.260.27270.600.134343034
42011-03-17spring2011Mar00Thursday1Clear0.380.39390.660.253741923

2-2. 별칭 사용하기 (Alias)

  • 임시로 컬럼명을 변경할 때 별칭을 사용할 수 있음.
⚠️ WARNING
기존의 컬럼명이 물리적으로 변경되는 것은 아님.
  • 별칭은 컬럼명 바로 뒤에 작성함.
  • 컬럼명과 별칭 사이에는 AS를 작성합니다. AS는 생략할 수 있음.
  • 특수문자, 대소문자, 공백을 사용하려면 따옴표(“ “ 또는 ‘ ‘)로 묶어주어야 함.
  • SELECT, FROM절에서 사용함.
  • 조인과 서브쿼리에서 테이블과 서브쿼리를 호출하기 위해 필수로 사용됨.
1
2
3
4
5
6
7
8
9
10
# bike테이블 이름을 'b'로 지정하고, b 테이블의 temp와 hum를 추출해보자.
# hum에 'humidity'이란 별칭을 주어보자.

mysql(""" 

SELECT temp, hum AS 'humidity'
FROM bike AS b
LIMIT 5

""")
temphumidity
00.240.81
10.220.80
20.220.80
30.240.75
40.240.75

3. 데이터 정렬과 중복 제거

3-1. 데이터 정렬하기(ORDER BY)

작성 순서

1
2
3
4
5
SELECT
FROM
WHERE
ORDER BY
LIMIT
  • SQL 구문 하단에 작성
  • 데이터 추출 시, 테이블에 입력된 순서대로 출력되는 것이 기본
  • 데이터가 오름차순, 내림차순으로 정렬된 형태가 필요할 때가 있음.
  • 오름차순 : 컬럼명 뒤에 ASC 적기.
    • ASC 생략해도 오름차순으로 정렬됨.

ORDER BY 컬럼명

  • 내림차순 : 컬럼명 뒤에 DESC 적기.

ORDER BY 컬럼명 DESC

  • SELECT 구문에 지정한 컬럼의 순서를 입력해도 실행 가능

` [예시] ORDER BY 1 DESC, 2 `

  • [해설] SELECT에 작성한 첫번째 컬럼 기준으로 내림차순으로 정렬하고, 같은 값이 있다면 두번째 컬럼 기준으로 정렬됨.
1
2
3
4
5
6
7
8
9
10
11
# dteday, temp, cnt 컬럼을 추출하고, cnt가 높은 순서대로 100개만 정렬 해보자.
# 순서가 같은 것이 있다면 temp가 낮은 순서대로 정렬하자

mysql("""

SELECT dteday, temp, cnt
FROM bike
ORDER BY cnt DESC, temp
LIMIT 100

""")
dtedaytempcnt
02012-09-120.66977
12012-09-200.64976
22012-09-110.70970
32012-09-100.62968
42012-09-250.66967
............
952012-06-110.80831
962012-03-230.70830
972012-07-110.80830
982012-10-110.50827
992012-05-310.76827

100 rows × 3 columns

1
2
3
4
5
6
7
8
9
# 컬럼 순서대로 입력하여 정렬
mysql("""

SELECT dteday, temp, cnt
FROM bike
ORDER BY 3 DESC, 2
LIMIT 100

""")
dtedaytempcnt
02012-09-120.66977
12012-09-200.64976
22012-09-110.70970
32012-09-100.62968
42012-09-250.66967
............
952012-06-110.80831
962012-03-230.70830
972012-07-110.80830
982012-10-110.50827
992012-05-310.76827

100 rows × 3 columns

3-2. 중복제거하기(DISTINCT)

  • 출력에서 고유한 값을 반환하기 위한 키워드
  • DISTINCT 키워드는 옆에 온 모든 컬럼을 고려하여 중복을 제거함.
  • 집계함수에도 DISTINCT를 사용할 수 있다.
    • [참고] 집계함수 : COUNT, SUM, AVG, MAX, MIN
1
2
3
4
5
6
7
8
9
# weekday, weathersit 컬럼에서 중복을 제거해보자. 

mysql(""" 

SELECT DISTINCT weekday, weathersit
FROM bike
LIMIT 5;

""")
weekdayweathersit
0SaturdayClear
1SaturdayCloudy
2SaturdayLightRain
3SundayCloudy
4SundayLightRain

4. 조건문 활용하기(IF, CASE WHEN ~ THEN ~)

4-1. IF(조건, 참일 때 반환 값, 거짓일 때 반환 값)

  • 단일 조건문
  • SELECT, WHERE 절에서 사용 가능합니다.
  • IF 내에 조건을 줄 때 함수와 함께 사용 가능합니다.
  • [참고] pandasql에서는 if 함수를 iif로 표현합니다.
1
2
3
4
5
6
7
8
9
10
#1990년 이전과 이후에 태어난 고객을 분리해 보자.

mysql("""
 
SELECT customerName AS "고객명"
    , birthday AS "생년월일"
    , iif(birthday >= '1990-01-01' , '이후', '이전') AS "1990년 기준"
FROM customers

""")
고객명생년월일1990년 기준
0Unai Bustinza1992. 2. 2이후
1Igor Bubnjic1992. 7. 17이후
2Gideon Jung1994. 9. 12이후
3Alberto Aquilani1984. 7. 7이전
4Nicola Strambelli1988. 9. 6이전
............
118Jeroen Vanthournout1989. 6. 29이전
119Raul Rusescu1988. 7. 9이전
120Konstantinos Fortounis1992. 10. 16이후
121Sami1988. 12. 18이전
122Szymon Drewniak1993. 7. 11이후

123 rows × 3 columns

4-2. CASE WHEN ~ THEN

  • 다중 조건문
  • 조건에 따른 값을 다르게 출력하고 싶은 경우 사용
    • 조건에 따라 기존에 있는 컬럼을 이용해 새로운 컬럼을 만들기도 함
  • 작성 순서
1
2
3
4
CASE WHEN '조건1' THEN '조건1 반환값'
     WHEN '조건2' THEN '조건2 반환값'
     ELSE '만족하는 조건이 없을 때 반환 값'
END
  • CASE문은 WHEN의 조건을 순차적으로 체크하고 조건이 충족되면 THEN에 명시된 값을 반환함.
    • WHENTHEN은 한 쌍으로 존재함.
    • WHENTHEN은 여러 개가 존재할 수 있음.
    • ELSE는 앞의 조건들에 모두 해당하지 않았을 때 정해줄 기본 값이다.
    • ELSE가 없고 조건에 맞는 값이 없으면 NULL값을 반환함.
💡 TIP
CASE WHEN, THEN, END를 먼저 작성한 후에 조건을 적으면 문법 실수를 줄일 수 있음.
1
2
3
4
5
6
7
8
9
10
11
# 고객 한도를 5만원, 십만원 단위로 분리해 보자.

mysql("""
SELECT customerName, creditLimit
   , CASE WHEN creditLimit <= 50000 THEN '5만원이하'
           WHEN creditLimit <= 100000 THEN '10만원이하'
           ELSE '10만원초과'
   END AS '고객한도분리'
FROM customers

""")
customerNamecreditLimit고객한도분리
0Unai Bustinza210005만원이하
1Igor Bubnjic7180010만원이하
2Gideon Jung11730010만원초과
3Alberto Aquilani11820010만원초과
4Nicola Strambelli8170010만원이하
............
118Jeroen Vanthournout6030010만원이하
119Raul Rusescu433005만원이하
120Konstantinos Fortounis8510010만원이하
121Sami11000010만원초과
122Szymon Drewniak8890010만원이하

123 rows × 3 columns


5. 데이터 타입 변환하기 (CAST)

5-1. CAST

  • 데이터의 타입을 변환하는 함수
  • 작성 순서

CAST(컬럼 AS 변환할 타입)

  • 변환할 타입에는 int, float, varchar(문자열), datetime(날짜) 등이 있음.
    • [예시] SELECT CAST(14.58 AS int) //14(결과값)
1
2
3
# 데이터 bike의 정보를 확인하자.

bike.info()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 17379 entries, 0 to 17378
Data columns (total 16 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   dteday      17379 non-null  object 
 1   season      17379 non-null  object 
 2   yr          17379 non-null  int64  
 3   mnth        17379 non-null  object 
 4   hr          17379 non-null  int64  
 5   holiday     17379 non-null  int64  
 6   weekday     17379 non-null  object 
 7   workingday  17379 non-null  int64  
 8   weathersit  17378 non-null  object 
 9   temp        17379 non-null  float64
 10  atemp       17379 non-null  float64
 11  hum         17379 non-null  float64
 12  windspeed   17379 non-null  float64
 13  casual      17379 non-null  int64  
 14  registered  17379 non-null  int64  
 15  cnt         17379 non-null  int64  
dtypes: float64(4), int64(7), object(5)
memory usage: 2.1+ MB

yr은 int 타입!

1
2
3
4
5
6
7
8
# 먼저 2011년 데이터 5개만 추출해 보자.

mysql("""
SELECT *
FROM bike
WHERE yr = 2011 
LIMIT 5
""")
dtedayseasonyrmnthhrholidayweekdayworkingdayweathersittempatemphumwindspeedcasualregisteredcnt
02011-01-01spring2011Jan00Saturday0Clear0.240.28790.810.031316
12011-01-01spring2011Jan10Saturday0Clear0.220.27270.800.083240
22011-01-01spring2011Jan20Saturday0Clear0.220.27270.800.052732
32011-01-01spring2011Jan30Saturday0Clear0.240.28790.750.031013
42011-01-01spring2011Jan40Saturday0Clear0.240.28790.750.0011
1
2
3
4
5
6
7
# 현재 int 타입인 yr을 varchar 타입으로 변경해 보자.

mysql("""
SELECT CAST(yr AS varchar) AS yr
FROM bike
LIMIT 5
""")
yr
02011
12011
22011
32011
42011
1
2
3
4
5
6
7
8
# yr을 문자열타입으로 변환한 후 2011년 데이터 5개만 추출해 보자.

mysql("""
SELECT CAST(yr AS varchar) AS yr
FROM bike
WHERE CAST(yr AS varchar)= '2011'
LIMIT 5
""")
yr
02011
12011
22011
32011
42011
1
bike.info()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 17379 entries, 0 to 17378
Data columns (total 16 columns):
 #   Column      Non-Null Count  Dtype  
---  ------      --------------  -----  
 0   dteday      17379 non-null  object 
 1   season      17379 non-null  object 
 2   yr          17379 non-null  int64  
 3   mnth        17379 non-null  object 
 4   hr          17379 non-null  int64  
 5   holiday     17379 non-null  int64  
 6   weekday     17379 non-null  object 
 7   workingday  17379 non-null  int64  
 8   weathersit  17378 non-null  object 
 9   temp        17379 non-null  float64
 10  atemp       17379 non-null  float64
 11  hum         17379 non-null  float64
 12  windspeed   17379 non-null  float64
 13  casual      17379 non-null  int64  
 14  registered  17379 non-null  int64  
 15  cnt         17379 non-null  int64  
dtypes: float64(4), int64(7), object(5)
memory usage: 2.1+ MB

-> 하지만 변경은 되지 않았다. 왜?

ℹ️ INFO
SQL에서 CAST() 함수는 조회(Query) 시점에서만 데이터를 변환하는 것 변경된 타입으로 결과를 보여줄 뿐, 원본 테이블 안에 있는 데이터 자체는 변하지 않음.
This post is licensed under CC BY 4.0 by the author.