write

[Fastcampus] RDC 강의 내용 정리 - 이부일 강사님

상관분석(Correlation Analysis)

When?
두 양적 자료 간에 관련성(직선의 관계 = 선형의 관계)이 있는지를 통계적으로 검정하는 방법

예제 데이터 : cars(speed, dist), attitude


1. 산점도(Scatter Plot)

(1) 기본

plot(x - data$variable, y - data$variable)
plot(cars$speed, cars$dist)

# 한 화면에 여러개 plot 출력
par(mfrow = c(2, 3))
for(i in colnames(attitude)[2:7]){
    plot(attitude[ , i], attitude$rating,
         main = paste("rating vs ", i),
         xlab = i,
         ylab = "rating",
         col = "blue",
         pch = 12)
}
par(mfrow = c(1, 1))


(2) 산점행렬도(SMP : Scatter Matrix Plot)

plot(iris[ , 1:4])


(3) 3D 산점도 : rgl, car package

with(iris,
     plot3d(Sepal.Length,
            Sepal.Width,
            Petal.Length,
            type="s",
            col=as.numeric(Species)))


scatter3d(x = iris$Sepal.Length,
          y = iris$Petal.Length,
          z = iris$Sepal.Width,
          groups = iris$Species,
          surface=FALSE,
          grid = FALSE,
          ellipsoid = TRUE,
          axis.col = c("black", "black", "black"))

(4) corrplot package

corrplot::corrplot(cor(iris[ , 1:4]), method = "circle")




2. 상관계수(Coefficient of Correlation)

두 양적 자료의 관련성(직선의 관계 = 선형의 관계) 정도를 수치로 알려줌
cor(datavariable,datavariable, datavariable, method = c("pearson", "spearman", "kendall"))

> cor(cars$speed, cars$dist, method = "pearson")
[1] 0.8068949

> cor(attitude, method = "pearson")
              rating complaints privileges  learning    raises  critical   advance
rating     1.0000000  0.8254176  0.4261169 0.6236782 0.5901390 0.1564392 0.1550863
complaints 0.8254176  1.0000000  0.5582882 0.5967358 0.6691975 0.1877143 0.2245796
privileges 0.4261169  0.5582882  1.0000000 0.4933310 0.4454779 0.1472331 0.3432934
learning   0.6236782  0.5967358  0.4933310 1.0000000 0.6403144 0.1159652 0.5316198
raises     0.5901390  0.6691975  0.4454779 0.6403144 1.0000000 0.3768830 0.5741862
critical   0.1564392  0.1877143  0.1472331 0.1159652 0.3768830 1.0000000 0.2833432
advance    0.1550863  0.2245796  0.3432934 0.5316198 0.5741862 0.2833432 1.0000000

> round(cor(attitude, method = "pearson") , digits = 3)
           rating complaints privileges learning raises critical advance
rating      1.000      0.825      0.426    0.624  0.590    0.156   0.155
complaints  0.825      1.000      0.558    0.597  0.669    0.188   0.225
privileges  0.426      0.558      1.000    0.493  0.445    0.147   0.343
learning    0.624      0.597      0.493    1.000  0.640    0.116   0.532
raises      0.590      0.669      0.445    0.640  1.000    0.377   0.574
critical    0.156      0.188      0.147    0.116  0.377    1.000   0.283
advance     0.155      0.225      0.343    0.532  0.574    0.283   1.000

> round(cor(iris[ , 1:4], method = "pearson") , digits = 3)
             Sepal.Length Sepal.Width Petal.Length Petal.Width
Sepal.Length        1.000      -0.118        0.872       0.818
Sepal.Width        -0.118       1.000       -0.428      -0.366
Petal.Length        0.872      -0.428        1.000       0.963
Petal.Width         0.818      -0.366        0.963       1.000```


3. 상관분석

  • 귀무가설 : speed와 dist 간에는 관련성이 없다.
  • 대립가설 : speed와 dist 간에는 관련성이 있다.
    cor.test(datavariable,datavariable, datavariable, method = "pearson")
> cor.test(cars$speed, cars$dist, method = "pearson")

	Pearson's product-moment correlation

data:  cars$speed and cars$dist
t = 9.464, df = 48, p-value = 1.49e-12
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.6816422 0.8862036
sample estimates:
      cor
0.8068949

유의확률이 0.000이므로 유의수준 0.05에서 speed와 dist 간에는 통계적으로 유의한 양의 상관관계가 있는 것으로 나타났다.
즉, speed가 증가하면 dist도 증가하는 경향을 보인다.



  • 귀무가설 : rating과 complaints 간에는 관련성이 없다.
  • 대립가설 : rating과 complaints 간에는 관련성이 있다.
> cor.test(attitude$complaints, attitude$rating, method = "pearson")

	Pearson's product-moment correlation

data:  attitude$complaints and attitude$rating
t = 7.737, df = 28, p-value = 1.988e-08
alternative hypothesis: true correlation is not equal to 0
95 percent confidence interval:
 0.6620128 0.9139139
sample estimates:
      cor
0.8254176

유의확률이 0.000이므로 유의수준 0.05에서 complaints와 rating 간에는 통계적으로 유의한 매우 높은 양의 상관관계가 있는 것으로 나타났다.



Quiz.

rating과 나머지 6개 변수 간의 관련성 검정을 해 보세요.

# for문 활용
for(i in colnames(attitude)[2:7]){
    print(cor.test(attitude[ , i], attitude$rating, method = "pearson"))
}

# corr.test 패키지 활용
> psych::corr.test(attitude, method = "pearson")

Call:psych::corr.test(x = attitude, method = "pearson")
Correlation matrix
           rating complaints privileges learning raises critical advance
rating       1.00       0.83       0.43     0.62   0.59     0.16    0.16
complaints   0.83       1.00       0.56     0.60   0.67     0.19    0.22
privileges   0.43       0.56       1.00     0.49   0.45     0.15    0.34
learning     0.62       0.60       0.49     1.00   0.64     0.12    0.53
raises       0.59       0.67       0.45     0.64   1.00     0.38    0.57
critical     0.16       0.19       0.15     0.12   0.38     1.00    0.28
advance      0.16       0.22       0.34     0.53   0.57     0.28    1.00
Sample Size
[1] 30
Probability values (Entries above the diagonal are adjusted for multiple tests.)
           rating complaints privileges learning raises critical advance
rating       0.00       0.00       0.19     0.00   0.01     1.00    1.00
complaints   0.00       0.00       0.02     0.01   0.00     1.00    1.00
privileges   0.02       0.00       0.00     0.07   0.15     1.00    0.51
learning     0.00       0.00       0.01     0.00   0.00     1.00    0.03
raises       0.00       0.00       0.01     0.00   0.00     0.36    0.01
critical     0.41       0.32       0.44     0.54   0.04     0.00    0.90
advance      0.41       0.23       0.06     0.00   0.00     0.13    0.00

 To see confidence intervals of the correlations, print with the short=FALSE option


Quiz.

housing data : price와 관련성이 있는 상위 6개의 변수명, 상관계수, t값, p-value를 출력하시오.

houseDF <- readxl::read_excel(path      = "kc_house_data.xlsx",
                              sheet     = 1,
                              col_names = TRUE)
View(houseDF)
houseDF$year <- 2018 - houseDF$yr_built
remove.variables <- c("id", "date", "floors", "waterfront", "view",
                      "condition", "yr_built", "yr_renovated",
                      "zipcode", "lat", "long")

houseDF2 <- houseDF %>%
    select(-one_of(remove.variables))
    #psych::corr.test()

corr.result <- psych::corr.test(houseDF2)
str(corr.result)
corr.result$r[ , 1]
str(corr.result$r)
top6.r <- round(sort(corr.result$r[, 1], decreasing = TRUE)[2:7], digits = 3)
top6.t <- round(sort(corr.result$t[, 1], decreasing = TRUE)[2:7], digits = 3)
top6.pvalue <- round(sort(corr.result$p[, 1], decreasing = TRUE)[2:7], digits = 3)
top6.variables <- names(round(sort(corr.result$r[, 1], decreasing = TRUE)[2:7], digits = 3))
plot(houseDF2[ , c(top6.variables, "price")])

corrDF <- data.frame(Variables = top6.variables,
                     r = top6.r,
                     t = top6.t,
                     pvalue = top6.pvalue)
writexl::write_xlsx(corrDF, path = "correlationResult.xlsx")


01Basic

[Fastcampus] RDC 강의 내용 정리 - 이부일 강사님

분산분석(ANOVA : Analysis of Variance)

When?
세 개 이상의 집단 간에 양적 자료에 차이가 있는지를 통계적으로 검정하는 방법

Use library & data

require("readxl")
require("nortest")
require("nparcomp")
require("PMCMR")
require("PMCMRplus")
require("writexl")

houseDF <- readxl::read_excel(path      = "kc_house_data.xlsx",
                              sheet     = 1,
                              col_names = TRUE)
View(houseDF)
str(houseDF)
table(houseDF$condition)
houseDF$condition <- as.factor(houseDF$condition)


1. 질적 자료 1개, 양적 자료 1개

질적 자료는 3개 이상의 유한 집단으로 구성되어 있어야 함.

  • 귀무가설 : condition에 따라 price에 차이가 없다.
  • 대립가설 : condition에 따라 price에 차이가 있다.

1단계 : 정규성 검정

  • 귀무가설 : 정규분포를 따른다.
  • 대립가설 : 정규분포를 따르지 않는다.
by(houseDF$price, houseDF$condition, ad.test)

2단계 : 정규성 가정이 만족이 되었다면

분산분석 : ANOVA
분산분석 결과 <- aov(양적자료 ~ 질적자료, data = dataname)

anova.result <- aov(price ~ condition, data = houseDF)
summary(anova.result)

<결과>
               Df           Sum Sq       Mean Sq F value       Pr(>F)    
condition       1    3851399435634 3851399435634   28.61 0.0000000894 ***
Residuals   21611 2909065362485666  134610400374                         
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1

유의확률이 0.000이므로 유의수준 0.05에서 condition에 따라 price에 통계적으로 유의한 차이가 있는 것으로 나타났다.


3단계 : 2단계의 결론이 대립가설이면

다중비교(Multiple Comparison) = 사후분석(Post-Adhoc)
Duncan, Tukey, Scheffee, Bonferroni, Dunnett

TukeyHSD(anova.result)

2단계 : 정규성 가정을 만족하지 않으면

Kruskal - Wallis Test
kruskal.test(양적자료 ~ 질적자료, data = dataname)

> kruskal.test(price ~ condition, data = houseDF)

	Kruskal-Wallis rank sum test

data:  price by condition
Kruskal-Wallis chi-squared = 260.85, df = 4, p-value < 2.2e-16

유의확률이 0.000이므로 유의수준 0.05에서 condition에 따라 price에 통계적으로 유의한 차이가 있는 것으로 나타났다.


3단계 : Kruskal-Wallis Test의 결론이 대립가설이면

다중비교 = 사후분석을 실시함
nparcomp::nparcomp(양적자료 ~ 질적자료, data = dataname)

> PMCMR::posthoc.kruskal.nemenyi.test(price ~ condition, data = houseDF,
+                                     dist="Tukey")

	Pairwise comparisons using Tukey and Kramer (Nemenyi) test
                   with Tukey-Dist approximation for independent samples

data:  price by condition

  1                 2                 3                 4                
2 0.99908           -                 -                 -                
3 0.000025063186814 < 2e-16           -                 -                
4 0.00023           0.000000000000046 0.000000544539610 -                
5 0.000000126256704 < 2e-16           0.000000000002318 0.000000000000046

P value adjustment method: none


Quiz

condition에 따라 price, bedrooms, bathrooms, sqft_living, sqft_lot, sqft_above, sqft_basement, year(2018 - yr_built)에 통계적으로 유의한 차이가 있는지를 검정하시오.

Variable Normaility Method F/Chisqaure pvalue
price No Krukal-Wallis 260.850 0.000
bathrooms Yes ANOVA 100.000 0.012
houseDF$year <- 2018 - houseDF$yr_built
analysis.variable <- c("price", "bedrooms", "bathrooms",
                       "sqft_living", "sqft_lot", "sqft_above",
                       "sqft_basement", "year")
Normality  <- c()
Method     <- c()
FChiSquare <- c()
PValue     <- c()
for(i in analysis.variable){
    normality.result <- by(unlist(houseDF[ , i]), houseDF$condition, ad.test)
    if(normality.result$`1`$p.value < 0.05 |
       normality.result$`2`$p.value < 0.05 |
       normality.result$`3`$p.value < 0.05 |
       normality.result$`4`$p.value < 0.05 |
       normality.result$`5`$p.value < 0.05){
        kruskal.result <- kruskal.test(unlist(houseDF[ , i]) ~ houseDF$condition)
        Normality  <- c(Normality, "No")
        Method     <- c(Method, "kruskal-Wallis")
        FChiSquare <- c(FChiSquare, kruskal.result$statistic)
        PValue     <- c(PValue, kruskal.result$p.value)
    }else{
        aov.result <- aov(unlist(houseDF[ , i]) ~ houseDF$condition)
        aov.result <- summary(aov.result)
        Normality  <- c(Normality, "Yes")
        Method     <- c(Method, "ANOVA")
        FChiSquare <- c(FChiSquare, unlist(aov.result)[7])
        PValue     <- c(PValue, unlist(aov.result)[9])
    }
}

anovaDF <- data.frame(Variables = analysis.variable,
                      Normality,
                      Method,
                      FChiSquare,
                      PValue)
writexl::write_xlsx(anovaDF, path = "anovaResult.xlsx")
01Basic

[Fastcampus] RDC 강의 내용 정리 - 이부일 강사님

Two Sample t-test

When?
두 개의 독립적인 집단의 평균이 같은지 다른지를 달라졌는지를 통계적으로 검정하는 방법
질적 자료(1개) : 두 집단
양적 자료(1개) :


  • 귀무가설 : 비졸업과 졸업 간에 용돈에 차이가 없다(mu1 = mu2).
  • 대립가설 : 비졸업과 졸업 간에 용돈에 차이가 있다(mu1 is not equal to mu2).

1단계 : 정규성 검정(Normality Test)

by(twosampleDF$money, twosampleDF$group, shapiro.test)

<결과>
twosampleDF$group: 비

	Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.83701, p-value = 0.02885

----------------------------------------------------------------------------------
twosampleDF$group: 졸

	Shapiro-Wilk normality test

data:  dd[x, ]
W = 0.57538, p-value = 6.737e-05

두 집단 모두 정규성 가정이 깨짐 => 2단계로 Wilcoxon's rank sum test를 실시


2단계 : 정규성 가정이 만족이 되면

등분산성 검정(Equality of Variance Test)

  • 귀무가설 : 등분산이다.
  • 대립가설 : 이분산이다.

var.test(datavariable datavariable ~ datavariable)
var.test(양적 자료 ~ 질적 자료)

> var.test(twosampleDF$money ~ twosampleDF$group)

	F test to compare two variances

data:  twosampleDF$money by twosampleDF$group
F = 0.22298, num df = 10, denom df = 11, p-value = 0.02499
alternative hypothesis: true ratio of variances is not equal to 1
95 percent confidence interval:
 0.06324512 0.81720812
sample estimates:
ratio of variances
         0.2229815

> by(twosampleDF$money, twosampleDF$group, var)
twosampleDF$group:[1] 1280.455
----------------------------------------------------------------------------------
twosampleDF$group:[1] 5742.424

결론 : 유의확률이 0.025이므로 유의수준 0.05에서 이분산이다.


3단계 : 이분산이 가정된 독립 2표본 t검정

t.test(data$variable ~ data$vairable,alternative = c("greater", "less", "two.sided"), var.equal = FALSE)

> t.test(twosampleDF$money ~ twosampleDF$group,
         alternative = "two.sided",
         var.equal   = FALSE)

<결과>
Welch Two Sample t-test

data:  twosampleDF$money by twosampleDF$group
t = -0.21741, df = 15.963, p-value = 0.8306
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -57.02012  46.41406
sample estimates:
mean in group 비 mean in group 졸
        76.36364         81.66667

유의확률이 0.831이므로 유의수준 0.05에서 비졸업자과 졸업자의 용돈에는 통계적으로 유의한 차이는 없는 것으로 나타났다.


3단계 : 등분산이 가정된 독립 2표본 t검정

t.test(data$variable ~ data$vairable, alternative = c("greater", "less", "two.sided"), var.equal = TRUE)

> t.test(twosampleDF$money ~ twosampleDF$group,
         alternative = "two.sided",
         var.equal   = TRUE)

	Two Sample t-test

data:  twosampleDF$money by twosampleDF$group
t = -0.21122, df = 21, p-value = 0.8348
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -57.51554  46.90948
sample estimates:
mean in group 비 mean in group 졸
        76.36364         81.66667

유의확률이 0.835이므로 유의수준 0.05에서 비졸업자과 졸업자의 용돈에는 통계적으로 유의한 차이는 없는 것으로 나타났다.


2단계 : 윌콕슨의 순위합 검정(Wilcoxon's rank sum test)

wilcox.test(data$variable ~ data$variable, alternative = c("two.sided", "greater", "less"))

> wilcox.test(twosampleDF$money ~ twosampleDF$group,
              alternative = "two.sided")

	Wilcoxon rank sum test with continuity correction

data:  twosampleDF$money by twosampleDF$group
W = 78, p-value = 0.4594
alternative hypothesis: true location shift is not equal to 0

유의확률이 0.459이므로 유의수준 0.05에서 비졸업자과 졸업자의 용돈에는 통계적으로 유의한 차이는 없는 것으로 나타났다.



Quiz 1.

  • yr_built : 1900이상 ~ 2000미만 : group = "old"
  • yr_built : 2000이상 : group = "new"
  • 귀무가설 : old와 new 간에 price에 차이가 없다.
  • 대립가설 : old가 new보다 price가 작다.
# 사용 데이터
houseDF <- readxl::read_excel(path      = "kc_house_data.xlsx",
                              sheet     = 1,
                              col_names = TRUE)

houseDF$group <-  cut(houseDF$yr_built,
                      breaks = c(1900, 2000, 2020),
                      right  = FALSE)
levels(houseDF$group) <- c("old", "new")
by(houseDF$price, houseDF$group, ad.test)
wilcox.test(houseDF$price ~ houseDF$group,
            alternative = "less")

result <- var.test(houseDF$price ~ houseDF$group)
result$p.value


Quiz 02.

id, date, yr_built를 제외한 모든 변수에 대해서 아래 가설검정을 실시

  • 귀무가설 : old와 new는 같다.
  • 대립가설 : new와 old는 같지 않다.

최종 결과 형태

variableName Normaility Method Equality TW pvalue
price yes t.test yes 1.234 0.123
bedrooms no wilcox.test non 1.234 0.123
houseDF <- read_excel(path      = "path/kc_house_data.xlsx",
                      sheet     = 1,
                      col_names = TRUE)
houseDF <- data.frame(houseDF)
# 분석에 사용하지 않는 변수 제거
# 1) dplyr (전처리에 많이 활용되는 라이브러리입니다.)
# select(변수 벡터)          => 지정벡터(열)만 추출
# select(-one_of(변수 벡터)) => 지정벡터(열)   제거
exceptVariable <- c("id", "date", "yr_built")
analysis.variable <- houseDF %>%
  select(-one_of(exceptVariable))

# 2) grep(base library)
analysis.variable <- colnames(houseDF)[-grep("^id|^date|^yr_built|^group",
                                             colnames(houseDF))]


# group 변수 생성
# ifelse를 활용하여 group - new/old 변수 생성 => 가설검정에서는 old를 기준으로 분석해야한다.
# default는 factor에서 new, old순서이기 때문에
# factor 형태 변환시 levels와 labels를 사용해서 old, new순서로 변경
# *주의) 데이터 형 변환시 as.factor와 factor는 동일한 기능을 수행하지만
#        levels와 lables를 argument로 가질 수 있는 것은 factor
houseDF$group <- ifelse(houseDF$yr_built >= 2000, "new","old")
str(houseDF$group)
table(houseDF$group)
houseDF$group <- factor(houseDF$group,
                        levels = c("old", "new"),
                        labels = c("old", "new"))
table(houseDF$group)

# 최종 결과를 저장하기 위한 빈 벡터 생성
Normality <- c()
Method    <- c()
Equality  <- c()
TW        <- c()
PValue    <- c() 

# for문(반복 횟수는 in (조건)에 들어간 벡터의 길이로 결정됩니다.)
# analysis.variable에서 변수를 한개씩 가져와서 실행
# for문의 반복 횟수는 19번(length(anaylsis.variable))
# 19번 동안 i에는 각각의 char타입의 열이름이 들어가서 실행
for(i in analysis.variable){

  # 1) 정규성 검정
  # 왜 unlist를 사용해야 하는가?
  # 우측 houseDF의 타입 : data.frame vs tbl_df
  # data.frame의 경우 houseDF[,i] 결과가 numveric vector입니다.
  # tbl_df의 경우 houseDF[,i] 결과가 tbl_df, data.frame형태의 class입니다.
  # 따라서, tbl_df형태를 가지는 houseDF는
  # 1) unlist를 통해서 벡터형태로 변환해주거나
  # 2) houseDF[, i]$변수명 형태로 한번더 슬라이싱을 해줘야 하는 문제가 있습니다.
    result.normality <- by(unlist(houseDF[ , i]), houseDF$group, ad.test)
    # result.normality <- by((houseDF[ , i]$i), houseDF$group, ad.test)
    # houseDF를 data.frame으로 변경하고 사용할 시
    # result.normality <- by(houseDF[ , i], houseDF$group, ad.test)

  # 2) 정규성 검정 결과를 통해 모수적 방법과 비모수적 방법 구분
  # 2-1) old와 new의 p-value가 둘중 하나라도 0.05 미만일 경우 정규성이 깨진다.
  #      => 비모수적행 방법 : wilcox.test
    if( (result.normality$old$p.value < 0.05) | (result.normality$new$p.value < 0.05)){
      # wilcox.test 결과 저장
        Normality <- c(Normality, "No")
        Method    <- c(Method, "wilcox.test")
        Equality  <- c(Equality, "Non")

        # 위의 unlist 설명과 동일
        # 대립 가설이 `old와 new가 같지 않다`이기 때문에 양측검정(two.sided)
        result.wilcox <- wilcox.test(unlist(houseDF[ , i])~ houseDF$group,
                                     alternative = "two.sided")

        # 필요한 부분만 추출하여 저장
        # str(result.wilcox)를 통해 wilcox 결과가 가지는 데이터의 구조를 확인 할 수 있습니다.
        TW     <- c(TW, result.wilcox$statistic)
        PValue <- c(PValue, result.wilcox$p.value)


  # 2-2) old와 newd의 p-value가 둘 모두 0.05 이상일 경우 정규성을 따른다.
  #     => 모수적 방법 : t-test
    }else{
        Normality <- c(Normality, "Yes")
        Method    <- c(Method, "t.test")

        # 3) 등분산성 검정
        # 귀무가설 : 등분산이다.
        # 대립가설 : 이분산이다.
        result.equality <- var.test(unlist(houseDF[ , i])~ houseDF$group)

        # p-value가 0.05 미만일 경우 이분산 (var.equal = FALSE)
        if(result.equality$p.value < 0.05){
            Equality  <- c(Equality, "No")
            result.ttest <- t.test(unlist(houseDF[ , i])~ houseDF$group,
                                   alternative = "two.sided",
                                   var.equal   = FALSE)
            TW     <- c(TW, result.ttest$statistic)
            PValue <- c(PValue, result.ttest$p.value)

        # p-value가 0.05 이상일 경우 등분산 (var.equal = TRUE)
        }else{
            Equality  <- c(Equality, "Yes")
            result.ttest <- t.test(unlist(houseDF[ , i])~ houseDF$group,
                                   alternative = "two.sided",
                                   var.equal   = TRUE)
            TW     <- c(TW, result.ttest$statistic)
            PValue <- c(PValue, result.ttest$p.value)
        }
    }
}

# for문을 6개의 벡터가 생성되었습니다.
# 하나의 결과로 저장
outputTest <- data.frame(Variable = analysis.variable,
                         Normality,
                         Method,
                         Equality,
                         TW,
                         PValue)
# 결과 내보내기
writexl::write_xlsx(outputTest, path = "outputTest.xlsx")
02Data

[Fastcampus] RDC 강의 내용 정리 - 이부일 강사님

One Sample t-test

When?
하나의 모집단의 양적 자료의 평균이 기존에 알고 있던 것보다
커졌는지, 작아졌는지, 달라졌는지를 통계적으로 검정하는 방법



1. 일표본 검정

  • 귀무가설 : 성인들의 평균 키는 170cm이다.
  • 대립가설 : 성인들의 평균 키는 170cm보다 크다.

1단계 : 정규성 검정(Normality Test)

  • 귀무가설 : 정규분포를 따른다.
  • 대립가설 : 정규분포를 따르지 않는다.

Shapiro-Wilk test : shapiro.test(data$variable)

height <- c(180, 175, 170, 170, 165, 184, 164, 159, 181, 167, 182, 186)
shapiro.test(height)

<결과>
Shapiro-Wilk normality test
data:  height
W = 0.93844, p-value = 0.4781

유의확률이 0.478이므로 유의수준 0.05에서 height는 정규분포를 따른다고 가정할 수 있다.


2단계 : 일표본 T검정(One sample t-test)

t.test(data$variable, mu = , alternative = )
mu : 귀무가설의 모평균
alternative : 대립가설, "greater", "less", "two.sided"

height.test <- t.test(height, mu = 170, alternative = "greater")
height.test

<결과>
One Sample t-test

data:  height
t = 1.3887, df = 11, p-value = 0.0962
alternative hypothesis: true mean is greater than 170
95 percent confidence interval:
 168.9492      Inf
sample estimates:
mean of x
 173.5833

유의확률이 0.096이므로 유의수준 0.05에서 성인들의 키는 통계적으로 유의하게 커지지 않았다. 성인들의 키는 변화가 없다.

str(height.test)
height.test$statistic    # t
height.test$parameter    # df
height.test$p.value      # p-value
height.test$conf.int     # 95% Confidence Interval, 신뢰구간
height.test$estimate     # 추정치, x bar, 표본의 평균
height.test$null.value   # 귀무가설의 모평균
height.test$alternative  # 대립가설
height.test$method       # One sample t-test
height.test$data.name    # height

2단계 : 윌콕슨의 부호 순위 검정(Wilcoxon's signed rank test)

wilcox.test(data$variable, mu = , alernative = )

wilcox.test(height, mu = 170, alternative = "greater")


Quiz 1.가설검정

귀무가설 : 성인들의 평균 용돈은 200만원이다.
대립가설 : 성인들의 평균 용돈은 200만원보다 작다.
유의수준 : 0.05

money <- c(45, 40, 40, 50, 50, 50, 40, 100, 50)

# 1단계 : 정규성 검정(Normality Test)
options(scipen = 100) # 지수 표현식 사용하지 않음
shapiro.test(money)
# 결론 : 유의확률이 0.000이므로 유의수준 0.05에서
# money는 정규분포를 따르지 않는다. 즉 정규성 가정을 만족하지 않음

# 2단계 : Wilcoxon's signed rank test
wilcox.test(money, mu = 200, alternative = "less")
# 결론 : 유의확률이 0.004이므로 유의수준 0.05에서
# 성인들의 용돈은 200만원보다 작다라는 대립가설을 채택
# 통계적으로 유의하게 성인들의 용돈이 줄어 들었다.


Quiz 2. 가설검정 결과 자동화 코드 작성

bedrooms", "bathrooms", "floors", "waterfront", "view", "condition", "grade" 변수에 대한 가설검정 결과를 엑셀 파일에 저장하시오.
귀무가설은 평균은 5이다로 함.

houseDF <- readxl::read_excel(path = "d:/da/kc_house_data.xlsx",
                              sheet = 1,
                              col_names = TRUE)

analysis.varibles <- c("bedrooms", "bathrooms", "floors", "waterfront", "view", "condition", "grade")


tv        <- c()
pvalue    <- c()
test.type <- c()

for(i in analysis.varibles){
    print(i)
    norm.test <- ad.test(unlist(houseDF[ , i]))
    if(norm.test$p.value > 0.05){
        result.t <- t.test(unlist(houseDF[ , i]), mu = 5, alternative = "two.sided")
        tv       <- c(tv, result.t$statistic)
        pvalue   <- c(pvalue, result.t$p.value)
        test.type <- c(test.type, "ttest")

    }else{
        result.wilcox <- wilcox.test(unlist(houseDF[ , i]), mu = 5, alternative = "two.sided")
        tv            <- c(tv, result.wilcox$statistic)
        pvalue        <- c(pvalue, result.wilcox$p.value)
        test.type <- c(test.type, "wilcox")
    }
}

resultDF <- data.frame(analysis.varibles, tv, pvalue, test.type)
writexl::write_xlsx(resultDF, path = "d:/da/resultDF.xlsx")

[Fast campus] Data Science with R 1기 - 이부일 강사님

공부하면서 배운 내용 복습 겸 정리하는 곳입니다.


# R.utils 패키지를 통해 printf() 사용 가능

install.packages("R.utils")

library(R.utils)


1. 반복문 : for

  # 동일한 일을 여러 번 하거나

  # 비슷한 일을 여러 번 할 때

1
2
3
4
5
6
7
8
9
10
11
12
13
> for(i in 1:10){
+   cat("hello,", i, "\n")
+ }
hello, 1 
hello, 2 
hello, 3 
hello, 4 
hello, 5 
hello, 6 
hello, 7 
hello, 8 
hello, 9 
hello, 10
cs

  # in은 대입, 할당하는 역할

  # 1:10 => 데이터의 개수(10개) 만큼 for문이 시행된다.

  # cat 대신 printf("hello, %d \n", i) 를 사용해도 동일한 결과 출력


  # 구구단

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
> for(i in 1:9){
+   cat(i, "단 이에요!""\n")
+   for(j in 1:9){
+     cat(i, "x", j, "=", i*j, "\n")
+   }
+   cat("\n")
+ }
 
1 단 이에요! 
1 x 1 = 1 
1 x 2 = 2 
1 x 3 = 3 
1 x 4 = 4 
1 x 5 = 5 
1 x 6 = 6 
1 x 7 = 7 
1 x 8 = 8 
1 x 9 = 9 
...
cs

  # 2~9단도 동일한 결과로 출력됨



2. 조건문

  (1) if( 조건 ){ 실행문 } - 조건이 TRUE면 실행문을 실행

1
2
3
4
5
6
7
8
9
> x = c(1003060)
> for(i in 1:3){
+   if(x[i] > 50){
+     printf("%d Very large number!!! \n", x[i])
+   } 
+ }
 
100 Very large number!!! 
60 Very large number!!!
cs


  (2) if (조건문) { 조건이 참일 때 실행문 1} 
       else{ 조건이 거짓일 때 실행문 2}

1
2
3
4
5
6
7
8
> y  = 10
> if(y > 5){
+   print("Large!!")
+ } else{
+   print("Small!!")
+ }
 
[1"Large!!"
cs


  (3) if( 조건문1) { 실행문 1 }

      else if( 조건문 2) { 실행문 2}

      else{ 실행문 3 }

# else if 조건 추가 가능

1
2
3
4
5
6
7
8
9
10
> z = 7
> if(z>10){
+   print("Large")
+ } else if(z>5){
+   print("medium")
+ } else{
+   print("small")
+ }
 
[1"medium"
cs



3. 사용자 함수

  # 함수명 = function( ) { 실행문 }

1
2
3
4
5
6
7
8
9
10
11
12
> hello = function(){
+   print("hello, world")
+   return("hello, fastcampus")
+ }
 
> hello()
[1"hello, world"
[1"hello, fastcampus"
 
> x = hello()
> x
[1"hello, world"
cs

  # return 의 의미를 생각


  # 숫자 x를 입력받으면 x*3 을 해주는 함수 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> triple = function(x){
+   if(mode(x) == "numeric"){
+  #if(is.numeric(x)) 을 사용해도 된다
+     tmp = 3*x
+     return (tmp)
+   } else{
+     print("숫자를 넣어주세요")
+   }
+ }
 
> triple(10)
[130
 
> triple("10")
[1"숫자를 넣어주세요"
cs


  # 구구단 : 해당 숫자의 구구단을 출력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> gugudan = function(x){
+   if(is.numeric(x)){
+     printf("%d단 \n", x)
+     for(i in 1:9){
+       printf("%d x %d = %d \n", x,i,x*i)
+     }
+   } else{
+     print("숫자를 넣어주세요")
+   }
+ }
 
> gugudan(3)
3단 
3 x 1 = 3 
3 x 2 = 6 
3 x 3 = 9 
3 x 4 = 12 
3 x 5 = 15 
3 x 6 = 18 
3 x 7 = 21 
3 x 8 = 24 
3 x 9 = 27
cs


[Fast campus] Data Science with R 1기 - 이부일 강사님

공부하면서 배운 내용 복습 겸 정리하는 곳입니다.


6. 새로운 변수 만들기

  # 데이터$변수명 = 연산(수식)

  # bmi 수치를 계산해서 새로운 변수로 추가

1
student$bmi = student$weight / ((student$height/100)^2)
cs


  # ifelse(조건, 참일 때 표현식, 거짓일 때 표현식)

  # 30대 이상 / 20대 이하를 나타내는 새로운 변수(age_group)를 추가

1
student$age_group = ifelse(student$age >= 30"30대 이상""20대 이하")
cs


  # 20대 초반, 20대 중반, 30대 이상으로 나뉘는 age_group2를 만들어라

1
2
student$age_group = ifelse(student$age >= 30"30대 이상",
                            ifelse(student$age >= 25"20대 중반""20대 초반")

cs


  # cut(데이터명$변수명, breaks = 구간정보) => numeric data에 적용

   경도 비만(1단계 비만) : 25 - 30

   과체중 : 23 - 24.9

   정상 : 18.5 - 22.9

   저체중 : 18.5 미만

1
2
student$bmi_group = cut(student$bmi, 
                        breaks = c(018.5232530))
cs

  # 데이터의 결과를 보면 ( ] 와 같이 소괄호 괄호로 표현된다

  # (18.5, 23] => 18.5 초과 23이하

  # ( ) 소괄호는 초과

  # [ ] 대괄호는 이하

  # 0과 30 초과 값들은 NA로 입력이됨

  # 위 코드에 right = FALSE 라는 argument 를 추가해보자

1
2
3
student$bmi_group = cut(student$bmi, 
                        breaks = c(018.5232530), 
                        right  = FALSE)
cs

  # right = FALSE 를 하게되면 괄호의 위치가 바뀌게 됨

  # [18.5, 23) => 18.5 이상 23미만

  # 30 이상의 값들은 NA로 표시됨


  # 각 행들의 평균 구하기

1
score$avg = rowMeans(score[ , 2:6])
cs

  # 각 열들의 평균은 colMeans( ) 



7. 데이터의 값을 수정하기

  # home 이라는 데이터

1
2
3
4
5
6
7
8
9
10
11
> home
# A tibble: 7 x 4
     id  room price  area
  <dbl> <dbl> <dbl> <dbl>
1     1     1    40     13
2     2     4 50000    55
3     3     3 20000    35
4     4     3 50000    35
5     5     1    43     2
6     6     4 50000    45
7     7     1   500    15
cs
  
  # 500이라는 값을 변경
1
2
3
4
5
6
7
8
9
10
11
12
> home[home$price == 500"price"] = 50
> home
# A tibble: 7 x 4
     id  room price  area
  <dbl> <dbl> <dbl> <dbl>
1     1     1    40     1
2     2     4 50000    55
3     3     3 20000    35
4     4     3 50000    35
5     5     1    43     2
6     6     4 50000    45
7     7     1    50    15 
cs



8. 데이터 정렬하기

  (1) 벡터를 정렬하기 : sort(벡터, decreasing = )

      # 기본값 = 오름차순

1
2
3
4
5
6
> money = c(455040505030500)
> sort(money)
[1]  30  40  45  50  50  50 500
 
> sort(money, decreasing = TRUE
[1500  50  50  50  45  40  30
cs

 

  (2) order(데이터명$변수명, decreasing = )

  # sort는 벡터에서만 사용가능

  # data.frame에서는 order 함수를 사용

1
2
> order(money)
[16 3 1 2 4 5 7
cs

  # order는 정렬될 인덱스를 알려준다.

  # data.frame에서 데이터 정렬은 행이 바뀌는 것

  # 슬라이싱의 행 자리에 order가 들어간다.


# 성별 내림차순

1
student[ order(student$height, decreasing = TRUE) , ]
cs


# 성별 내림차순 / 키 내림차순

1
student[ order(student$gender, student$height, decreasing = TRUE ) , ]
cs


# 성별 오름차순 / 키 내림차순

# 조건이 다르니 -를 사용

1
student[ order(student$gender, -student$height) , ]
cs


# 성별 내림차순 / 키 오름차순

# - 는 numeric에만 적용 가능

1
student[ order(student$gender, -student$height, decreasing = TRUE ) , ]
cs


# 성별 오름차순 / 거주지 내림차순

# character 타입의 데이터를 따로 정렬하려면? 

# - 는 numeric에만 적용된다 => 기본 기능에서는 불가능

# data.table 패키지를 사용하여 데이터를 data.table로 변경

1
studentDT = as.data.table(student), ]
cs
# str(studentDT)를 통해 확인해보면 data.frame, data.table 2가지 형태를 모두 인식하는 것을 볼 수 있다.

1
studentDT[ order(gender, -address) , ]  
cs

# 데이터의 column에 바로 접근 가능

# 결과를 콘솔 화면에 보여주기만 함

 

1
setorder(studentDT, gender, -address)  
cs

# setorder( ) 를 사용하면 데이터를 정렬해서 결과 저장


※ data.frame vs data.table 참고

http://using.tistory.com/81 

# data.table()_cheet sheet 확인

# setkey(), J(), fread() 공부



9. 데이터 합치기

  (1) rbind(데이터1, 데이터2, ... ) => 위, 아래로 데이터 합치기


  (2) merge(데이터1, 데이터2, ..., by=, all=, all.x=, all.y=)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> df4 = data.frame(id  = c(1247),
+                  age = c(10204070))
> df5 = data.frame(id = c(123610),
+                  gender = c("M""M""F""M""F"))
> df4;df5
  id age
1  1  10
2  2  20
3  4  40
4  7  70
  id gender
1  1      M
2  2      M
3  3      F
4  6      M
5 10      F
cs


# merge 4가지 방법

① inner join(교집합)

# inner join은 2가지 데이터만, 3가지 이상은 다른 기능으로

# by는 PK(Primary Key) => 데이터를 구분해주는 값 

# PK 예) 사람-주민등록번호, 회사직원-사원

1
2
3
4
> merge(df4, df5, by="id")
  id age gender
1  1  10      M
2  2  20      M
cs


# outer join

② full join(합집합) - all=TRUE

1
2
3
4
5
6
7
8
9
> merge(df4, df5, by="id", all=TRUE)
  id age gender
1  1  10      M
2  2  20      M
3  3  NA      F
4  4  40   <NA>
5  6  NA      M
6  7  70   <NA>
7 10  NA      F
cs

# R에서 숫자는 NA / 문자는<NA>로 표시해서 구분해준다.


③ left join - all.x=TRUE

1
2
3
4
5
6
> merge(df4, df5, by="id", all.x=TRUE)
  id age gender
1  1  10      M
2  2  20      M
3  4  40   <NA>
4  7  70   <NA>
cs


④ right join - all.y=TRUE

1
2
3
4
5
6
7
> merge(df4, df5, by="id", all.y=TRUE)
  id age gender
1  1  10      M
2  2  20      M
3  3  NA      F
4  6  NA      M
5 10  NA      F
cs



10. R데이터 저장하기

  (1) 외부 데이터로 저장하기

1
2
3
write.csv(student,
          file      = "fs/data/student.csv",
          row.names = FALSE)
cs

# row.names = FALSE 를 주게되면 행 이름은 저장하지 않음


  (2) R데이터로 저장하기

1
save(R데이터, file = "파일위치/파일명.RData")
cs


  (3) R데이터 불러오기

1
load(file = "파일위치/파일명.RData") 
cs


[Fast campus] Data Science with R 1기 - 이부일 강사님

공부하면서 배운 내용 복습 겸 정리하는 곳입니다.


Data Handling = Data Pre-processing


## 사용할 데이터 읽어오기

# 외부 데이터를 읽어오면 data.frame 형태로 저장된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
> student = readxl::read_excel(path = "fs/data/student.xlsx",
+                              sheet = "data",
+                              col_names = TRUE)
> student
# A tibble: 12 x 8
      id gender   age height weight  address
   <dbl>  <chr> <dbl>  <dbl>  <dbl>    <chr>
 1     1   남자    29    188     80   구파발
 2     2   남자    28    185     63     강동
 3     3   남자    25    172     63 압구정동
 4     4   여자    24    160     48     수원
 5     5   남자    26    180     80     용인
 6     6   남자    26    188     77     성수
 7     7   남자    59    170     63     수원
 8     8   여자    25    160     45     분당
 9     9   남자    27    178     78     강동
10    10   남자    31    181     95     의왕
11    11   여자    27    167     58     길동
12    12   남자    40    175     70     부산
# ... with 2 more variables: major <chr>,
#   company <chr>
cs


1. 데이터 전체보기

  (1) View(데이터) 

View(student)

# 별도의 팝업 창으로 데이터를 볼 수 있음

  

  (2) 데이터 : 콘솔(Console)에 출력

student



2. 데이터 구조(Structure) 보기

  (1) str(데이터)

str(student)

1
2
3
4
5
6
7
8
9
10
> str(student)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame':    12 obs. of  8 variables:
 $ id     : num  1 2 3 4 5 6 7 8 9 10 ...
 $ gender : chr  "남자" "남자" "남자" "여자" ...
 $ age    : num  29 28 25 24 26 26 59 25 27 31 ...
 $ height : num  188 185 172 160 180 188 170 160 178 181 ...
 $ weight : num  80 63 63 48 80 77 63 45 78 95 ...
 $ address: chr  "구파발" "강동" "압구정동" "수원" ...
 $ major  : chr  "경영정보학" "산업경영학" "경영학" "수학" ...
 $ company: chr  "NC소프트" "구글" "아마존" "SK" ...
cs

# student의 id만 보고 싶다면 => str(student$id)



3. 데이터의 일부 보기

  (1) head(데이터) 

# 상위 6개의 데이터를 보여줌

1
2
3
4
5
6
7
8
9
10
11
12
> head(student)
# A tibble: 6 x 8
     id gender   age height weight  address
  <dbl>  <chr> <dbl>  <dbl>  <dbl>    <chr>
1     1   남자    29    188     80   구파발
2     2   남자    28    185     63     강동
3     3   남자    25    172     63 압구정동
4     4   여자    24    160     48     수원
5     5   남자    26    180     80     용인
6     6   남자    26    188     77     성수
# ... with 2 more variables: major <chr>,
#   company <chr>
cs

# head(student, n = 3)

# 출력 데이터 개수 지정 가능

  

  (2) tail(데이터)

# 하위 6개의 데이터를 보여줌

# head와 동일한 출력 형태

# tail(student)

# tail(student, n = 3)



4. 데이터 프레임의 속성

  (1) 행의 개수 : nrow(데이터)

1
2
> nrow(student)
[112
cs


  (2) 열의 개수 => 변수의 개수 : ncol(데이터)

1
2
> ncol(student)
[18
cs


  (3) 행의 이름 : rownames(데이터)

# 결과는 character

1
2
3
> rownames(student)
 [1"1"  "2"  "3"  "4"  "5"  "6"  "7"  "8" 
 [9"9"  "10" "11" "12"
cs

  

  (4) 열의 이름 => 변수의 이름 : colnames(데이터)

# 결과는 character

1
2
3
> colnames(student)
[1"id"      "gender"  "age"     "height" 
[5"weight"  "address" "major"   "company"
cs


  (5) 차원(dimension) : 행, 렬 : dim(데이터)

1
2
3
4
5
6
7
8
> dim(student)
[112  8
 
> dim(student)[1
[112
 
> dim(student)[2
[18
cs


  (6) 차원의 이름 : 행의 이름, 열의 이름 : dimnames(데이터)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
> dimnames(student)
[[1]]
 [1"1"  "2"  "3"  "4"  "5"  "6"  "7"  "8" 
 [9"9"  "10" "11" "12"
 
[[2]]
[1"id"      "gender"  "age"     "height" 
[5"weight"  "address" "major"   "company"
 
> dimnames(student)[1#리스트
[[1]]
 [1"1"  "2"  "3"  "4"  "5"  "6"  "7"  "8" 
 [9"9"  "10" "11" "12"
 
> dimnames(student)[[1]] #벡터
 [1"1"  "2"  "3"  "4"  "5"  "6"  "7"  "8" 
 [9"9"  "10" "11" "12"
 
> dimnames(student)[[1]][3#벡터(dimnames(student)[[1]]) 의 3번 째 값
[1"3"
cs


5. 데이터(data.frame)의 슬라이싱

  # 데이터[행index, 열index] => data.frame은 행,열의 2차원 구조

  # Vectorization 이 적용됨, for문 없이 연산이 끝까지 수행


  (1) 열(column) 

# 데이터[ , index]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> student[ , 2]
# A tibble: 12 x 1
   gender
    <chr>
 1   남자
 2   남자
 3   남자
 4   여자
 5   남자
 6   남자
 7   남자
 8   여자
 9   남자
10   남자
11   여자
12   남자
cs


문제. 짝수번째 열 가져오기

1
2
3
student[ , seq(from = 2,
               to   = ncol(student),
               by   = 2)] 
cs

# vector 에서는 length

# data.frame 에서는 nrow, ncol


문제. weight, height의 데이터를 가져오기

1
student[ , c("weight""height")
cs

# index가 character 이므로 c( )를 사용


# 변수명에 특정한 패턴이 있는 것을 추출

# grep("패턴", 문자열)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 변수명 중에서 'e'라는 글자를 포함하고 있는 변수명의 위치
grep("e"
     colnames(student))
 
# 'e'라는 글자를 포함하고 있는 변수명
grep("e"
     colnames(student), 
     value=TRUE
 
# 'e'라는 글자를 포함하고 있는 데이터를 추출
student[ , grep("e"
                colnames(student), 
                value=TRUE)]
 
# 'a'라는 글자로 시작하는 데이터를 추출 => ^a
student[ , grep("^a"
                colnames(student), 
                value=TRUE)]
 
# 't'라는 글자로 끝나는 데이터를 추출 => t$
student[ , grep("t$"
                colnames(student), 
                value=TRUE)]
 
# 't'라는 글자로 끝나거나, 'a'라는 글자로 시작하는 데이터를 추출
student[ , grep("t$|^a"
                colnames(student), 
                value=TRUE)]
cs

# 정규표현식을 익히자

# https://wikidocs.net/1669 

# http://www.nextree.co.kr/p4327/


  (2) 행(row)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 성별이 여자인 데이터만 가져오기
student.female = student[student$gender == "여자"]
 
# 거주지가 수원이 아닌 사람들의 데이터
student[student$address != "수원"]
 
# 몸무게가 50 이하인 사람들의 데이터
student[student$weight <= 50]
 
# 나이가 30대 이상이고, 키는 175 이상인 사람
student[(student$age >= 30& (student$height >= 175), ]
 
# 나이가 30대 이상이거나 키는 175 이상인 사람
student[(student$age >= 30| (student$height >= 175), ]
cs


  (3) 행, 열

1
2
3
4
# 키가 170cm 이상이고, 몸무게가 60kg 이상인 사람들 중에서 
# 변수명에 'e'라는 글자가 들어가는 데이터
student[(student$height >= 170& (student$weight >= 60), 
        grep("e", colnames(student))]
cs








[Fast campus] Data Science with R 1기 - 이부일 강사님

공부하면서 배운 내용 복습 겸 정리하는 곳입니다.


외부 데이터 : txt, csv, excel(xls, xlsx) 


1. 텍스트 데이터 : txt

  (1) 구분자(Separator) : 공백 하나(blank, white space)

1
2
3
데이터명 = read.table(file  = "파일위치/파일명.txt",
                     header = TRUE,
                     sep    = " "
cs


  (2) 구분자(Separator) : comma(,)

1
2
3
데이터명 = read.table(file   = "파일위치/파일명.txt",
                     header = TRUE,
                     sep    = ","
cs


  (3) 구분자(Separator) : 탭(tab)

1
2
3
데이터명 = read.table(file   = "파일위치/파일명.txt",
                     header = TRUE,
                     sep    = "\t"
cs



2. CSV(Comma Separated Value)

# 엑셀의 특수한 형태

1
2
3
데이터명 = read.table(file   = "파일위치/파일명.txt",
                     header = TRUE,
                     sep    = "\t"
cs


3. 엑셀 : xls, xlsx

# R의 기본 기능에서는 못 읽어 옴

# 추가 기능(패키지(Package))을 설치 - install.packages("패키지명")

# 패키지 로딩하기, 구동하기 - library(패키지명)

1
2
3
4
5
6
> install.packages("readxl")
package ‘readxl’ successfully unpacked and MD5 sums checked

The downloaded binary packages are in
    C:\Users\JungChul\AppData\Local\Temp\RtmpG8Gy4u\downloaded_packages
> library(readxl)
cs

  # 패키지 설치 명령어 후 successfully 메시지가 나오면 설치 완료

  # 패키지는 항상 코드 가장 위( 다른 pc에서 실행 할 수도 있으니 install.packages명령어도 같이 적어두기 )

  # 패키지 내 함수를 사용할 때는 '패키지명::함수' 형태로 사용하자

1
2
3
데이터명 = readxl::read_excel(path="파일위치/파일명.xlsx",
                             sheet=index or "시트명",
                             col_names=TRUE)
cs


[Fast campus] Data Science with R 1기 - 이부일 강사님

공부하면서 배운 내용 복습 겸 정리하는 곳입니다.


IV. 배열(Array)
  # 다차원
  # vector, 행렬의 확장
  # 벡터의 특징( Recycling Rule, Vectorization ) 그대로 적용됨
  # array(vector, dim=)
1
2
> array(1:10, dim=10)
 [1]  1  2  3  4  5  6  7  8  9 10
cs
  # dim에 1개의 숫자
  # 1차원 형태를 지닌 벡터의 결과

1
2
3
4
5
> array(1:10, dim=3:4)
     [,1[,2[,3[,4]
[1,]    1    4    7   10
[2,]    2    5    8    1
[3,]    3    6    9    2
cs
  # dim에 3,4 => 2개의 숫자
  # 2차원 형태를 지닌 행렬의 결과

1
2
3
4
5
6
7
8
9
10
11
12
13
14
> array(1:10, dim=c(3,4,2))
, , 1
 
     [,1[,2[,3[,4]
[1,]    1    4    7   10
[2,]    2    5    8    1
[3,]    3    6    9    2
 
, , 2
 
     [,1[,2[,3[,4]
[1,]    3    6    9    2
[2,]    4    7   10    3
[3,]    5    8    1    4
cs
  # dim에 숫자 3,4,2 => 3개의 숫자
  # 3행 4열 2높이 => 3차원


V. 데이터 프레임(Data.Frame)
  # 행, 열로 구성. 2차원
  # 여러 개의 데이터 유형을 가질 수 있음 
  # 단, 하나의 열은 하나의 데이터 유형만 가짐 
  # data.frame(벡터1, 벡터2, 행렬, ...)
1
2
3
4
5
6
7
8
9
10
11
> id = 1:5
> gender = c("m""m""m""f""m")
> address = c("구파발""강동""압구정""수원""용인")
> survey = data.frame(id, gender, address)
> survey
  id gender address
1  1      m  구파발
2  2      m    강동
3  3      m  압구정
4  4      f    수원
5  5      m    용인
cs


VI. 리스트(List)
  # 분석한 결과를 저장할 때에 많이 사용하는 형태
  # 가장 유연한 데이터 형태
  # 리스트의 원소로 vector, factor, matrix, array, data.frame, list를 가질 수 있다.
  # list(vector, factor, matrix, array, data.frame, list, ...)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
> v1 = 1:10
> v2 = 1:3
> v3 = c("ch""nu""lo")
> v4 = c(TRUEFALSE)
> m1 = cbind(v1, v2)
> result = list(v1, v2, v3, v4, m1, survey)
> result
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10
 
[[2]]
[11 2 3
 
[[3]]
[1"ch" "nu" "lo"
 
[[4]]
[1]  TRUE FALSE
 
[[5]]
      v1 v2
 [1,]  1  1
 [2,]  2  2
 [3,]  3  3
 [4,]  4  1
 [5,]  5  2
 [6,]  6  3
 [7,]  7  1
 [8,]  8  2
 [9,]  9  3
[10,] 10  1
 
[[6]]
  id gender address
1  1      m  구파발
2  2      m    강동
3  3      m  압구정
4  4      f    수원
5  5      m    용인
 
cs

  리스트의 슬라이싱
  # 리스트의 슬라이싱은 [ ] , [[ ]]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
> a1 = result[1]
> a2 = result[[1]]
> a1
[[1]]
 [1]  1  2  3  4  5  6  7  8  9 10
 
> a2
 [1]  1  2  3  4  5  6  7  8  9 10
 
> b1 = result[4]
> b2 = result[[4]]
> b1
[[1]]
[1]  TRUE FALSE
 
> b2
[1]  TRUE FALSE
cs

  # 대괄호 1개 사용 : 결과는 list

  # 대괄호 2개 사용 : numeric, character, logical, list로 나타남.

 


[Fast campus] Data Science with R 1기 - 이부일 강사님

공부하면서 배운 내용 복습 겸 정리하는 곳입니다.


II. 요인(Factor)

  # 벡터의 일종

  # 차이점 : 집단(group)으로 인식함

  # 1차원 - 하나의 열로 구성

  # 벡터는 집단으로 인식하지 않음

  # factor(vector, labels=, levels=, ordered=) 


  bt(blood type) 예제

1
2
3
> bt = c("ab""ab""a""a""b")
> bt
[1"ab" "ab" "a"  "a"  "b"
cs


  bt를 factor로 바꿔보자

1
2
3
4
> bt_factor <- factor(bt)
> bt_factor
[1] ab ab a  a  b 
Levels: a ab b
cs

  # Levels : a ab b => 3개의 집단(a, ab, b)으로 인식함    


  bt_factor2 - labels

1
2
3
4
5
> bt_factor2 <- factor(bt, 
                       labels = c("A형","AB형","B형"))
> bt_factor2
[1] AB형 AB형 A형  A형  B형 
Levels: A형 AB형 B형
cs

  # labels : 데이터 값과 결과가 바뀜


  bt_factor3 - levels

1
2
3
4
5
> bt_factor3 <- factor(bt,
                       levels = c("b","ab","a"))
> bt_factor3
[1] ab ab a  a  b 
Levels: b ab a
cs

  # levels : 집단의 순서 - 데이터 자체는 바뀌지 않지만 b, ab, a 순으로 Levels이 바뀌게 됨


  bt_factor4 - labels, levels

1
2
3
4
5
6
> bt_factor4 <- factor(bt,
+                      levels = c("b","ab","a"),
+                      labels = c("B형","AB형","A형"))
> bt_factor4
[1] AB형 AB형 A형  A형  B형 
Levels: B형 AB형 A형
cs

  # 2개의 argument 같이 사용할 시 labels의 값들은 levels에 대응되도록 사용해야 한다


  bt_factor5

1
2
3
4
5
6
7
> bt_factor5 <- factor(bt, 
+                      levels  = c("b","ab","a")
+                      labels  = c("A형","AB형","B형"),
+                      ordered = TRUE)
> bt_factor5
[1] AB형 AB형 B형  B형  A형 
Levels: A형 < AB형 < B형
cs

  # ordered : 특정한 결과값을 의미있게 구분할 때 사용 => 부등호가 나타남


 factor의 속성

  (1) levels(요인)

1
2
> levels(bt_factor)
[1"a"  "ab" "b" 
cs

  (2) ordered(요인)

# 집단의 순서가 의미 있도록 변경

1
2
3
> ordered(bt_factor)
[1] ab ab a  a  b 
Levels: a < ab < b
cs

# bt_factor의 속성을 ordered=TRUE로 만들어 주겠다는 것



III. 행렬(Matrix)

  # 행(row)와 열(column)로 구성되어 있음

  # 2차원 (행, 열)

  # 벡터의 확장 -> 1차원에서 2차원으로

  # 벡터의 규칙이 대부분 적용( Recycling Rule, Vectorization )


  1. 행렬을 만드는 방법

(1) rbind(벡터1, 벡터2, ...)  /  cbind(벡터1, 벡터2, ...)

1
2
3
4
5
6
7
> v1 = 1:3
> v2 = 4:6
> M1 = rbind(v1, v2)
> M1
   [,1[,2[,3]
v1    1    2    3
v2    4    5    6
cs

# rbind : row를 기준으로 벡터를 결합하여 생성

# cbind : column을 기준으로 벡터를 결합하여 생성


(2) matrix(vector, nrow=, ncol=, byrow=)

1
2
3
4
> matrix(1:4, nrow=2, ncol=2)
     [,1[,2]
[1,]    1    3
[2,]    2    4
cs

# R에서 행렬은 열(column)이 우선으로 채워진다.


1
2
3
4
> matrix(1:4, nrow=2, ncol=2, byrow=TRUE)
     [,1[,2]
[1,]    1    2
[2,]    3    4
cs

# byrow = TRUE는 행(row)을 우선으로 행렬을 채우는 것



  2. 행렬의 슬라이싱

     # 행렬[ 행index, 열index ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
> M3
     [,1[,2]
[1,]    1    2
[2,]    3    4
 
> M3[1]    # 1행
[11 2
 
> M3[2]    # 2행
[13 4
 
> M3[1:2]  #1,2행 
     [,1[,2]
[1,]    1    2
[2,]    3    4
 
> M3[ ,1 ]    # 2열
[11 3
 
> M3[ ,1:2 ]  # 1,2열
     [,1[,2]
[1,]    1    2
[2,]    3    4
 
> M3[1,2]   # 1행, 2열
[12
 
cs

  


3. 행렬의 덧셈과 뺄셈

# 형태(shape)가 동일해야 한다. 

# 2x3 은 2x3 끼리만 연산 가능

1
2
3
4
5
6
7
8
9
10
11
12
> A <- matrix(1:4, nrow=2, ncol=2)
> B <- matrix(5:8, nrow=2, ncol=2)
 
> A + B
     [,1[,2]
[1,]    6   10
[2,]    8   12
 
> A - B
     [,1[,2]
[1,]   -4   -4
[2,]   -4   -4
cs


# A*B -> 행렬의 곱셈? 

1
2
3
4
> A * B
     [,1[,2]
[1,]    5   21
[2,]   12   32
cs

# A*B는 단순히 index가 같은 값 끼리 연산하는 것으로 행렬의 곱셈은 아니다.


  4. 행렬의 곱셈

# A_r1,c1 %*% B_r2,c2

# 조건 : c1 = r2 -> 곱하고자 하는 A의 열과 B의 행의 개수가 같아야 한다.

# 최종 결과는 r1xc2 matrix

1
2
3
4
5
6
> A = matrix(1:4, nrow=2, ncol=2)
> B = matrix(5:8, nrow=2, ncol=2)
> A %*% B
     [,1[,2]
[1,]   23   31
[2,]   34   46
cs



  5. 역행렬(Reverse Matrix)

# 조건 1 : 정방행렬(Square Matrix) - 행과 열의 개수가 같음

# 조건 2 : 행렬식이 0이 아니어야 함

ex) 

A( a11, a12

    a21, a22)

# 조건 1 : 2x2 행렬

# 조건 2 : (a11 x a22) - (a12 x a21) != 0

# 조건 2가지가 성립하므로 역행렬 결과는

A( a22, -a12

    -a21, a11)

# 위의 결과에 1/(a11 x a22) - (a12 x a21) 을 곱해줌

# solve() 함수를 사용하여 역행렬을 구함 

1
2
3
4
5
6
7
8
9
10
11
> A1 = matrix(1:4, nrow=2, ncol=2)
> A1
     [,1[,2]
[1,]    1    3
[2,]    2    4
 
> A2 = solve(A1)
> A2
     [,1[,2]
[1,]   -2  1.5
[2,]    1 -0.5
cs


# A1과 A2(A1의 역행렬)을 곱하면 단위행렬이 나옴

1
2
3
4
> A1 %*% A2
     [,1[,2]
[1,]    1    0
[2,]    0    1
cs


# 방정식 계산

2x + y = 3

-x + 3y = 10

1
2
3
4
5
6
> B1 = matrix(c(21-13), nrow=2, ncol=2)
> B2 = matrix(c(310), nrow=2, ncol=1)
> solve(B1) %*% B2
         [,1]
[1,] 2.714286
[2,] 2.428571
cs

 


  6. 전치행렬(Transpose Matrix)

# 행과 열을 바꿈

# t(행렬)

1
2
3
4
5
6
7
8
9
> A
     [,1[,2]
[1,]    1    3
[2,]    2    4
 
> t(A)
     [,1[,2]
[1,]    1    2
[2,]    3    4
cs


+ Recent posts