Just Fighting

[Spark] 데이터 전처리하기(spark sql사용, 결측값 처리) 본문

Big Data

[Spark] 데이터 전처리하기(spark sql사용, 결측값 처리)

yennle 2022. 3. 15. 01:22
728x90

필요한 데이터를 만들기 위해서 데이터를 합치고, 값을 변경하고, 결측치를 처리했다.

 

 

먼저 항상 그랬듯이 연결부터!

import findspark

findspark.init()
# spark 생성

import pyspark
from pyspark.sql import SparkSession

spark = SparkSession.builder.getOrCreate()

 

4가지의 데이터를 합치고자 했기 때문에 다 불러왔다.

show()를 이용해 잘 가져와졌는지 확인도 했다.

match_data = spark.read.csv("hdfs://localhost:19000/data/match_data_2.csv", header="true", inferSchema="true")
winrate = spark.read.csv("hdfs://localhost:19000/data/winrate.csv", header="true", inferSchema="true")
winrate_team = spark.read.csv("hdfs://localhost:19000/data/winrate_team.csv", header="true", inferSchema="true")
winrate_team_recent = spark.read.csv("hdfs://localhost:19000/data/winrate_team_recent.csv", header="true", inferSchema="true")

 

데이터를 합치기 위해서 spark sql을 사용했다.

먼저 뷰를 생성해준 뒤에 sql문을 작성해 원하는 대로 데이터를 합쳐준다.

# 뷰 생성

match_data.createOrReplaceTempView("match")
winrate.createOrReplaceTempView("player")
winrate_team.createOrReplaceTempView("team")
winrate_team_recent.createOrReplaceTempView("recent")

위에서 불러온 match_data를 match라는 이름의 뷰로 만들겠다는 의미가 된다!

# 데이터 값 변환

# 선수별 승률, 팀 승률, 최근 2주간 승률 데이터 join
# win의 값 => W 이면 1, L이면 0
# (숫자)+'%'인 문자열을 (숫자)로 만들어줌

data = spark.sql("SELECT if(match.win='W',1,0) as win, float(replace(a.winrate,'%','')) as topwr, float(replace(b.winrate,'%','')) as jgwr,\
    float(replace(c.winrate,'%','')) as midwr, float(replace(d.winrate,'%','')) as adcwr, float(replace(e.winrate,'%','')) as supwr,\
    float(replace(team.winrate,'%','')) as teamwr, float(replace(recent.winrate1,'%','')) as recentwr1, float(replace(recent.winrate2,'%','')) as recentwr2 from match\
    left join player a on match.date=a.date and match.top1 like CONCAT('%', a.player1) and match.top2 like CONCAT('%', a.player2)\
    left join player b on match.date=b.date and match.jg1 like CONCAT('%', b.player1) and match.jg2 like CONCAT('%', b.player2)\
    left join player c on match.date=c.date and match.mid1 like CONCAT('%', c.player1) and match.mid2 like CONCAT('%', c.player2)\
    left join player d on match.date=d.date and match.adc1 like CONCAT('%', d.player1) and match.adc2 like CONCAT('%', d.player2)\
    left join player e on match.date=e.date and match.sup1 like CONCAT('%', e.player1) and match.sup2 like CONCAT('%', e.player2)\
    left join team on match.date=team.date and match.team1=team.team1 and match.team2=team.team2\
    left join recent on match.date=recent.date and match.team1=recent.team1 and match.team2=recent.team2")

< 시행착오 >

더보기

처음에 sql문에서 변수 따로 안건드렸다가 아래 코드도 작성했는데

그냥 아래 코드 안 쓰고 sql 코드를 변경했음 ㅎㅎㅎ

이런 함수도 있다는 것을 기억하기 위해 남겨놓음!

# 데이터 값 변환

#  win의 값 => W 이면 1, L이면 0
# (숫자)+'%'인 문자열을 (숫자)로 만들어줌

from pyspark.sql.functions import translate
from pyspark.sql.types import IntegerType,FloatType

aa = aa.withColumn('win', translate(aa.win, 'L','0').cast('int'))
aa = aa.withColumn('win', translate(aa.win, 'W','1').cast('int'))
aa = aa.withColumn('topwr', translate(aa.topwr, '%','').cast('float'))
aa = aa.withColumn('jgwr',translate(aa.jgwr, '%','').cast('float'))
aa = aa.withColumn('midwr',translate(aa.midwr, '%','').cast('float'))
aa = aa.withColumn('adcwr',translate(aa.adcwr, '%','').cast('float'))
aa = aa.withColumn('supwr',translate(aa.supwr, '%','').cast('float'))
aa = aa.withColumn('teamwr',translate(aa.teamwr, '%','').cast('float'))
aa = aa.withColumn('recentwr1',translate(aa.recentwr1, '%','').cast('float'))
aa = aa.withColumn('recentwr2',translate(aa.recentwr2, '%','').cast('float'))

 

위의 4개의 데이터를 이용해 데이터를 원하는 대로 만들 수 있었다.

대충 설명하자면 날짜별로 선수 대 선수 승률과 팀 대 팀 승률, 팀의 최근 2주간 승률 데이터를 합친 것이다.

이 때 문자열로 저장된 승률 데이터를 퍼센트를 지우고 float형으로 변경해주었다.

 

 

마지막으로 결측값을 처리했다.

결측값이 있는 행을 제거할까 했는데 새로 들어온 데이터에도 무조건 결측값이 없을 거라는 보장이 없어서

값을 변경하는 것으로 정했고, 승률이다 보니 0이면 한번도 못 이긴게 되고 100이면 다 이긴게 되는거라

너무 왜곡된 데이터가 될 것 같아서 50으로 null값을 채워주는 걸로 결정했다.

아래 코드는 결측값이 얼마나 있는지 확인할 수 있는 코드다.

# 결측값 개수 보기

from pyspark.sql.functions import isnan, when, count, col, isnull

data.select([count(when(isnull(c), c)).alias(c) for c in data.columns]).show()

# 결측값 처리

# 승률이기 때문에 아예 경기를 치르지 않았을 경우 50으로 채워 넣는다.

data = data.na.fill(50)

 

전처리 끝~!~!

 

 

728x90
Comments