<jupyter_start><jupyter_text>EDA(Exploratory Data Analysis) - EDA : 탐색적 자료 분석, 즉 수집한 자료를 `다양한 각도에서 관찰하고 이해`하는 과정으로 그래프나 통계적 방법을 이용해서 자료를 직관적으로 파악하는 과정을 말한다. `자료의 분포와 통계를 파악하여 자료가 갖고 있는 특성을 이해`하고, 잠재적인 문제를 발견해서 분석전에 발견이 어려운 다양한 문제점을 발견하고 이를 바탕으로 기존의 가설을 수정하거나 새로운 방향의 가설을 세울 수 있다. - EDA는 분석에 필요한 자료를 이해하고 자료의 전처리 그리고 정제된 데이터셋을 대상으로 변수 간의 특성을 분석하는 데 필요하다.   - 1) 분석의 목적과 변수의 특징 확인    - 수집된 자료를 대상으로 셀 수 없는 변수와 셀 수 있는 변수를 구분한다.  - 2) 자료 확인 및 전처리    - 수집된 자료를 확인하고 결측치와 이상치를 확인하고 정제한다.  - 3) 자료의 각 변수 관찰    - 대표값이나 산포도를 이용한 통계 조사 및 이산변수와 연속변수 시각화  - 4) 변수 간의 관계에 초점을 맞춰 패턴 발견    - 변수와 변수 간의 상관관계이나 고급 시각화 도구를 이용한 변수 간의 패턴 발견 --- - 1) 수집 자료 이해  - 예를 들면 자료 구조, 관측치의 길이, 변수 구성, 각 변수의 의미, 측정 방법, 척도 유형 등을 확인한다. 수집 자료의 이해는 자료로부터 의미 있는 통찰을 얻는 출발점이다.  - 데이터의 분포 현황을 통해서 데이터의 유형과 결측치(NA) 그리고 극단치(outlier)등의 데이터를 발견할 수 있다. 결측치는 응답자의 회피와 응답할 수 없는 상황(예를 들면 여성인 경우 군필 항목)에서 주로 발생하며, 극단치는 데이터의 수집과 입력과정에서 실수로 발생한다.<jupyter_code>getwd()
setwd('C:/Users/ehfus/Downloads/R')
dataset = read.csv('dataset.csv',header=T)
head(dataset)
names(dataset)<jupyter_output><empty_output><jupyter_text>- print() 함수의 결과는 콘솔 창에서 확인할 수 있고, View() 함수의 결과는 별도의 창을 통해 테이블 형식으로 확인할 수 있다. - 여기서는 jupyter notebook으로 실행하기 때문에 생략한다.<jupyter_code>tail(dataset)<jupyter_output><empty_output><jupyter_text>- 2) 데이터 셋 구조 보기  - 분석에 필요한 `데이터 셋의 구조`를 확인하는 함수는 `names(),attributes(),str()` 함수 등이 있다. 이러한 함수들을 이용하여 데이터 셋의 세부정보를 조회할 수 있다. 특히 attributes() 함수는 열 이름과 행 이름 그리고 자료구조 정보를 제공하며 str() 함수는 자료구조 그리고 관측치와 변수의 개수를 제공한다.<jupyter_code>names(dataset)
# 변수명(칼럼) 조회
attributes(dataset)
# 열,행,그리고 자료구조 정보 제공
str(dataset)<jupyter_output>'data.frame':	300 obs. of  7 variables:
 $ resident: int  1 2 NA 4 5 3 2 5 NA 2 ...
 $ gender  : int  1 1 1 2 1 1 2 1 1 1 ...
 $ job     : int  1 2 2 NA 3 2 1 2 1 2 ...
 $ age     : int  26 54 41 45 62 57 36 NA 56 37 ...
 $ position: int  2 5 4 4 5 NA 3 3 5 3 ...
 $ price   : num  5.1 4.2 4.7 3.5 5 5.4 4.1 675 4.4 4.9 ...
 $ survey  : int  1 2 4 2 1 2 4 4 3 3 ...<jupyter_text>- 3) 데이터 셋 조회  - 데이터 셋에 포함된 특정 변수의 내용을 조회하는 방법에 대해서 알아본다.<jupyter_code>names(dataset)
dataset$resident
length(dataset$resident)<jupyter_output><empty_output><jupyter_text>- 위의 특정 변수의 조회 결과를 변수에 저장하기<jupyter_code>x = dataset$age
x<jupyter_output><empty_output><jupyter_text>- 산점도 그래프로 변수 조회<jupyter_code>plot(dataset$price)
# x축은 index 즉, price의 순서?이니까 딱 300개가 있을 것이다.<jupyter_output><empty_output><jupyter_text>- 칼럼명을 이용하여 특정 변수 조회<jupyter_code>head(dataset['gender'])<jupyter_output><empty_output><jupyter_text>- 색인을 사용하여 특정 변수 조회<jupyter_code>dataset[2]
# 두 번째 칼럼 조회
# 칼럼이 default
dataset[3,]
# 3번째 행, 모든 열
dataset[,3]
dataset[3]<jupyter_output><empty_output><jupyter_text>- 2개 이상의 칼럼 조회<jupyter_code>dataset[c('age','price')]
dataset[c(2,6)]<jupyter_output><empty_output><jupyter_text>--- - 결측치 처리  - na.rm=T 또는 na.omit() 함수를 통해 결측치를 제거한 후 유효한 자료만을 대상으로 연산할 수도 있다. 하지만 무조건 결측치를 제거한다면 그로 인하여 중요한 데이터가 손실될 수 있다. 따라서 결측치를 처리하는 방법에는 결측치를 제거하는 방법도 있지만 결측치를 제거하지 않고 다른 값으로 대체하는 방법도 고려해볼 수 있다.  - 결측치 확인<jupyter_code>summary(dataset$price)<jupyter_output><empty_output><jupyter_text>- 결측치가 30개 있다.<jupyter_code>sum(dataset$price) # error
sum(dataset$price,na.rm=T) # 무시
sum(na.omit(dataset$price))
# na.omit() 함수는 결측치를 제거한 후 남은 것을 반환해준다.<jupyter_output><empty_output><jupyter_text>- 결측치 대체 (0으로 대체하거나 평균으로 대체한다.)<jupyter_code># NA이면 0으로 대체
ifelse(!is.na(dataset$price),dataset$price,0)
# 결측치를 평균으로 대체
ifelse(!is.na(dataset$price),dataset$price,round(mean(dataset$price,na.rm=T),2))
# 이렇게 기존 df에 새로운 칼럼을 만들어줄 수 있음
dataset$newprice = ifelse(!is.na(dataset$price),dataset$price,round(mean(dataset$price,na.rm=T),2))
dataset$newprice<jupyter_output><empty_output><jupyter_text>- 극단치 처리  - 극단치 : 표본 중 다른 대상들과 확연히 구분되는 통계적 관측치를 의미한다. 즉, 변수의 분포에서 비정상적으로 분포를 벗어난 값을 극단치(outlier)라고 한다. 예를 들면 나이의 분포는 0세 이상 100세 사이의 분포를 보이는 것이 일반적이지만 -2 또는 230과 같은 비정상적인 수치가 보인다면 이는 극단치에 해당한다. 또한 변수와의 상관관계에 있어서 높은 직급의 경력사원이 직급이나 낮은 일반 사원보다 급여가 월등하게 적다면 이 또한 비정상적인 수치로 의심해볼 수 있다.  - 범주형 변수 극단치 처리  - 성별과 같은 변수를 컴퓨터로 처리하기 위해서는 남자(1), 여자(2)와 같이 수치 데이터로 표현해야 한다. 이렇게 명목상 수치로 표현된 변수들을 범주형(명목척도)이라고 한다.   - 범주형 변수들을 대상으로 극단치를 확인하고 이를 토대로 데이터를 정제하는 과정을 알아보자<jupyter_code>table(dataset$gender)
pie(table(dataset$gender))
dataset = subset(dataset,gender==1|gender==2)
# subset은 데이터 셋의 특정 변수를 대상으로 조건식에 해당하는 레코드(행)를 추출하여 별도의 변수에 저장하는 경우 유용한 함수이다.
dataset
# subset 함수를 이용하여 데이터를 정제한 것이다. (gender==5인 경우는 걸러낸 것이다. subset으로!)
length(dataset$gender)<jupyter_output><empty_output><jupyter_text>- 원래는 300개였는데 297개로 3개 줄어듦을 확인할 수 있다.<jupyter_code># 정제 결과 확인
pie(table(dataset$gender),col=c('red','blue'))<jupyter_output><empty_output><jupyter_text>- 연속형 변수의 극단치 처리  - 연소득이나 구매금액 등 연속된 데이터를 갖는 변수들을 대상으로 극단치를 확인하고 이를 토대로 데이터를 정제해보자<jupyter_code>dataset = read.csv('dataset.csv', header=T)
length(dataset$price) # NA를 포함하여 300개의 데이터가 있다. 
plot(dataset$price) # 산점도를 이용하여 가격 분포 보기
summary(dataset$price) # -457~675까지 분포되어 있음<jupyter_output><empty_output><jupyter_text>- price 변수의 데이터 정제와 시각화<jupyter_code># price 변수 전제 (2~8)
dataset2 = subset(dataset,price>=2 & price<=8)
length(dataset2$price)
# 줄기와 잎 도표
stem(dataset2$price)<jupyter_output>The decimal point is at the |

  2 | 133
  2 | 
  3 | 0000003344
  3 | 55555888999
  4 | 000000000000000111111111222333334444
  4 | 566666777777889999
  5 | 00000000000000000011111111111222222222333333344444
  5 | 55555555566667777778888899
  6 | 00000000000000111111112222222222222333333333333333344444444444
  6 | 55557777777788889999
  7 | 000111122
  7 | 777799<jupyter_text>- age 변수의 데이터 정제와 시각화<jupyter_code>summary(dataset2$age)
length(dataset2$age)
# age 변수 정제, NA 제거
dataset2 = subset(dataset2, age>=20 & age<=69)
length(dataset2$age)<jupyter_output><empty_output><jupyter_text>- 극단치를 찾기 어려운 경우  - 범주형 변수를 일정한 범주를 가지고 있기 때문에 극단치를 찾는 데 큰 어려움이 없다. 하지만 구매 가격과 같은 연속 변수는 극단치를 찾기 어려울 수 있따. 실제 VIP 고객은 일반 고객과 비교하여 평균 구매금액이 월등히 많은 경우를 종종 볼 수 있따. 이런 경우 값의 범위에서 상하위 0.3 %를 극단치로 보여주는 boxplot와 통계를 이용해 볼 수 있다.<jupyter_code>boxplot(dataset$price)<jupyter_output><empty_output><jupyter_text>- 극단치 통계 확인<jupyter_code>boxplot(dataset$price)$stats<jupyter_output><empty_output><jupyter_text>- 이를 통해 극단치를 제거한 서브 셋을 만들자<jupyter_code>dataset_sub = subset(dataset,price>=2.1&price<=7.9)
summary(dataset_sub$price)<jupyter_output><empty_output><jupyter_text>--- - 코딩 변경  - 최초 코딩 내용을 용도에 맞게 변경하는 작업을 의미.데이터 가독성과 척도 변경 그리고 역 코딩 등의 목적으로 수행. - 1) 가독성을 위한 코딩 변경  - 일반적으로 데이터는 디지털화하기 위해서 숫자로 코딩한다.     - 예를 들면 거주지 관련 칼럼에서 서울은 1, 인천은 2로 코딩한다. 이런 코딩 결과를 대상으로 기술통계분석을 수행하면 1과 2의 숫자를 실제 거주지명으로 표현해야 한다. 실습해보자<jupyter_code>head(dataset2)<jupyter_output><empty_output><jupyter_text>- resident 칼럼을 보면 실제 거주지명이 아닌 1,2,3,4,5로 표현되어 있음을 알 수 있다. - dataset2의 resident 칼럼으로 조건식을 지정하여 거주지역별로 실제 거주지명을 resident2 칼럼에 추가한다.<jupyter_code>dataset2$resident2[dataset2$resident == 1] = '1.서울특별시'
dataset2$resident2[dataset2$resident == 2] = '2.인천광역시'
dataset2$resident2[dataset2$resident == 3] = '3.대전광역시'
dataset2$resident2[dataset2$resident == 4] = '4.대구광역시'
dataset2$resident2[dataset2$resident == 5] = '5.시구군'<jupyter_output><empty_output><jupyter_text>- 코딩 변경 전과 변경 후의 칼럼을 살펴보자<jupyter_code>head(dataset2[c('resident','resident2')])<jupyter_output><empty_output><jupyter_text>- 동일한 원리를 통해 job칼럼에도 코딩변경을 수행하여 가독성을 향상시켜줄 수 있다.  --- - 척도 변경을 위한 코딩 변경<jupyter_code># 나이를 나타내는 age 칼럼을 대상으로 코딩 변경해보자
dataset2$age2[dataset2$age<=30] = '청년층'
dataset2$age2
dataset2['age2']<jupyter_output><empty_output><jupyter_text>- 역 코딩을 위한 코딩 변경  - 만족도 평가를 위해서 설문지 문항을 5점 척도인 매우만족, 만족, 보통, 불만족, 매우 불만족 형태로 작성된 경우 순서대로 코딩하면 매우 만족이 1 그리고 매우 불만족이 5로 코딩된다. 이러한 만족도 평가를 점수화하기 위해서는 매우 만족과 매우 불만족이 역순으로 변경되어야 하는데 이러한 작업을 역코딩이라고 한다.<jupyter_code>head(dataset2['survey'])<jupyter_output><empty_output><jupyter_text>- 예를 들면 만족도(survey) 칼럼을 대상으로 1~5 순서로 코딩된 값을 5~1 순서로 역코딩하기 위해서는 6-현재값 형식으로 수식을 적용하면 된다.<jupyter_code>survey = dataset2$survey
dataset2$survey2 = 6 - survey
dataset2['survey2']<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.109375, 'fraction_numerical': 0.0628842213114754, 'mean_word_length': 4.558007117437723, 'pattern_counts': {'":': 0, '<': 107, '<?xml version=': 0, '>': 106, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 13, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '26', 'dir': 'jupyter-structured-clean-dedup', 'id': '639429', 'license': 'Apache-2.0', 'n_tokens_mistral': 5720, 'n_tokens_neox': 6773, 'n_words': 1026, 'path': '_notebooks/2022-02-15-r.ipynb', 'repo_name': 'rhkrehtjd/INTROr', 'size': '7808'}