반응형

     정보

    • 업무명     : R을 통한 지니계수 계산 및 시각화

    • 작성자     : 박진만

    • 작성일     : 2020-12-06

    • 설   명      :

    • 수정이력 :

     

     내용

    [개요]

    • 안녕하세요? 웹 개발 및 연구 개발을 담당하고 있는 해솔입니다.

    • 다년간 축적된 경험 (기상학 학술 보고서 및 국/영문 학술 논문 게재, 블로그 운영, IT 회사 웹 개발 담당) 및 노하우를 바탕으로 개개인에게 맞춤형 솔루션을 수행할 수 있습니다.

    • 특히 재능 플랫폼 (크몽, 오투잡, 해피캠퍼스, 레포트 월드)에서 누구보다도 경쟁력 있는 가격으로 양질의 서비스를 제공하고 있습니다.

      • 아스키 형식의 텍스트 (text) 파일부터 과학자료 형식 (HDF, H5, NetCDF, Grib, Grb) 및 Data Base (DB) 자료까지 다양한 형태의 자료를 이용하여 수집, 전처리, 분석, 시각화해 드립니다.

      • 또한 웹 사이트에 대한 정보를 이용한 웹 크롤링 및 그에 따른 엑셀 및 DB 구축도 가능합니다.

      • 아울러 기초 통계 (빈도분포, Prired t-test, Wilcoxn 등)에서 지도/비지도 학습을 통한 회귀모형 구축에 이르기 까지 효율적인 통계 정보를 제공합니다.

      • 최근 대한민국의 후속위성인 천리안위성 2A호 웹 서비스 서브시스템 및 환경위성 2B호 통합 자료처리 서브시스템에 대한 웹 개발을 수행하였습니다.

    • 그리고 해솔 블로그에서는 다양한 기상학/천문학 정보와 더불어 사무 자동화/프로그래밍 언어를 소개하오니 방문 부탁드립니다.

    • 좋은 하루 보내세요.

     

    [재능플랫폼] 오투잡

     

    [IT개발 - 응용프로그래밍] 통계 분석, 데이터 분석, 시각화를 성실하게 해 드립니다. - 재능마켓 �

    판매가격:10,000원, [소개] - 데이터산업진흥원 데이터 가공 공급기업 선정 - 정보통신산업 진흥원 데이터 가공 공급기업 선정 - 다년간 축적된 경험 노하우를 바탕으로 개개인에게 맞춤형 솔루션�

    www.otwojob.com

     

    [재능플랫폼] 크몽

     

    데이터수집, 파싱, 크롤링 해 드립니다. | 50,000원부터 시작 가능한 총 평점 0점의 IT·프로그래밍,

    0개 총 작업 개수 완료한 총 평점 0점인 shlee1990의 IT·프로그래밍, 데이터분석·리포트, 데이터 마이닝·크롤링 서비스를 0개의 리뷰와 함께 확인해 보세요. IT·프로그래밍, 데이터분석·리포트, 데

    kmong.com

     

     요청

    [세부 사항]

    • R 스크립트를 이용하여 지니계수 산출 함수 작성

    • 아래와 같은 그래프 생성

     

     

     완료

    [사용 OS]

    • Windows 10

     

    [사용 언어]

    • R v4.0.2

     

    [명세]

    • 지니계수를 계산 및 시각화 함수 작성

    giniValue <- function(data = data,income_col = income_col,plotFlag = FALSE,plotName = "result",plotPath = "./",...){
        
      addArg <- list(...)
    
      if(length(addArg) >= 1) {
        
       for (j in 1:length(addArg)) {
      
         nn <- as.data.frame(addArg[j])
         params <- data.frame(dum = c())
    
         if(nn[2,1] == "numeric"){ 
           
         for (k in 3:nrow(nn)) {
           param <- as.numeric(nn[k,1])
           params <- rbind(params,param)
         }
           
         } else if (nn[2,1] == "character") {
           
           for (k in 3:nrow(nn)) {
             param <- as.character(nn[k,1])
             params <- rbind(params,param)
           }
           
         } else {
           return("ERROR : 자료형의 입력이 잘못 되었습니다.")
         }
         
         # col name 재설정
         newColName = nn[1,1]
         colnames(params)[1] <- newColName
         # col name 재설정
         
         ### 데이터 필터링 ###
         data <- dplyr::inner_join(data,params,by=newColName)
         ### 데이터 필터링 ###
         
         # print(data)
         
         if(nrow(data) == 0) {
           return("조건에 맞는 데이터가 없습니다.")
         }
    
       }
       
      }
    
      # print(head(data))
      
      # 필터링된 데이터 선택 #
      x <- data[[income_col]]
      x_L1 <- sort(x)
      x_sum <- sum(x_L1)
      x_len <- length(x_L1)
      # 필터링된 데이터 선택 #
      
      # 지니계수 계산
      g = REAT::gini(x, lc = FALSE, lcx = "% of objects", 
                     lcy = "% of regarded variable", lctitle = "Lorenz curve", lcg = FALSE, 
                     lcgn = FALSE)
      
      
      # plotflag 여부에 따라 그림을 출력할지 말지 결정 #
      if(isTRUE(plotFlag)) {
        
      xx <- c()
      xy <- c()
      xw <- c()
      
      # x축 : 인구누적비율
      # y축 : 소득누적비율
      
      # 로렌츠 커브의 넓이를 계산하기 위한 코드
      tt <- 0
      
      for (i in 1:x_len) {
        
        isx <- i/x_len
        
        tt = tt+x_L1[i]
        
        isy <- tt/x_sum
        
        w <- (1/x_len) * isy
        
        xx <- append(xx,isx)
        xy <- append(xy,isy)
        xw <- append(xw,w)
        
      }
      # 로렌츠 커브의 넓이를 계산하기 위한 코드
      
      ############## w1 플로팅을 위한 위치좌표 설정  ############## 
      nis = seq(1,x_len,1)/x_len
      which_w1 = which.max(nis-xy)
      w1 = c(xx[which_w1],(nis[which_w1]+xy[which_w1])/2,0.5-round(sum(xw),4))
      ############## w1 플로팅을 위한 위치좌표 설정  ############## 
      
      # 결과를 데이터프레임에 저장
      res <- data.frame(x = xx, y = xy)
      
      ggplot(data = res) +
        theme_bw() +
        theme(text = element_text(size=14,face = "bold"),
              plot.title= element_text(size=18,face = "bold")) +
        geom_line(aes(x=xx,y=xy),size = 1.5,color = "blue") + 
        geom_text(aes(0.07, 0.97, label = paste0("G : ",round(g,4))),size = 5) +
        geom_text(aes(0.07, 0.92, label = paste0("N : ",length(x))),size = 5) +
        geom_text(aes(w1[1], w1[2], label = paste0("W1 = ",w1[3])),size = 5) +
        geom_abline(size = 1.5, color = "black") +
        # xlim(0,1) +
        # ylim(0,1) +
        xlab("인구 누적 비율") +
        ylab("소득 누적 비율") +
        labs(title = "gini value") +
        scale_x_continuous(expand = expansion(mult = c(0.01, 0.01)),breaks = c(0,0.25,0.5,0.75,1.0),limits = c(0,1)) +
        scale_y_continuous(expand = expansion(mult = c(0, 0)),breaks = c(0,0.25,0.5,0.75,1.0)) +
        ggsave(paste0(plotPath,plotName,".png"),dpi = 300,width = 8, height = 8)
      
      }
      
        # 지니계수 리턴
        return(g)
    
    }

     

    • 데이터 로드 및 함수 사용

    ######## 최초 실행시 한번만 수행 ###########
    # install.packages("haven")
    # install.packages("dplyr")
    # install.packages("tidyr")
    # install.packages("ggplot2")
    # install.packages("labelled")
    # install.packages("reldist")
    # install.packages("lawstat")
    # install.packages("REAT")
    # install.packages("stringr")
    # install.packages("openxlsx")
    # install.packages("installr")
    ######## 최초 실행시 한번만 수행 ###########
    
    ######## 라이브러리 로드 ##############
    library(installr)
    installr::install.rtools()
    Sys.setenv(R_ZIPCMD= "C:/Rtools/bin/zip")
    # library(haven)
    library(dplyr)
    library(tidyr)
    library(ggplot2)
    library(foreign)
    library(labelled)
    library(reldist)
    library(lawstat)
    library(REAT)
    library(stringr)
    library(openxlsx)
    ######## 라이브러리 로드 ##############
    
    
    # sav 데이터 읽기
    #gini_sav_data <- read_spss("c:/workgini/gini_sav_data_Lnoin.sav") #경로는 임의로 변경 가능함
    gini_sav_data <- read_spss("./gini_sav_data_Lnoin.sav") #경로는 임의로 변경 가능함
    
    
    #컬럼이름 정하기
    colnames(gini_sav_data) <- c("year","h_reg5","h_reg7","h_din","h_cin","h01_1","h01_1s","h01_4","h01_11","h01_110",
                                 "ex_1","ex_2","ex_3","ex_4","ex_5","ex_6","ex_7","ex_8","ex_9",
                                 "total_living_expenses","total_expen_notax","earned_income","business_income","proberty_income",
                                 "etc_income","pub_pension","pri_pension","total_income","equalized_produc_income","equalized_income",
                                 "rank10","old","gen")  #컬럼은 임의로 변경 가능함
    
    # 추가 
    # 해당 명령어를 이용하여 데이터의 형태를 간략하게 조회해볼 수 있음 
    glimpse(gini_sav_data)
    
    
    # factor to character
    ## dbl+l 데이터가 존재하는 경우 이를 character로 만들기 위한 작업임 ##
    # dplyr::mutate(as.character(to_factor(컬림이름))...) 을 통해 변경 가능
    
    gini_sav_data_Lnoin <- gini_sav_data %>%
      dplyr::mutate(h_reg5 = as.character(as_factor(h_reg5)),
                    h_reg7 = as.character(as_factor(h_reg7)),
                    h01_4 = as.character(as_factor(h01_4)),
                    h01_110 = as.character(as_factor(h01_110)),
                    h01_11 = as.character(as_factor(h01_11)),
                    rank10 = as.numeric(rank10),
                    gen = as.numeric(gen))   
                    
                    
                    
    g_full <- c()
    
    for (y in 2007:2018) {
      
      g <- giniValue(data = gini_sav_data_Lnoin,income_col = "total_income", # 총 소득
                     param1 = c("year","numeric",y), # y를 대입 (2007 ~ 2018)
                     param2 = c("old","numeric",under65old), #65세 미만 (under65old)
                     plotFlag = TRUE,
                     plotPath = "C:\\tmpimg\\", # 이미지를 저장할 경로를 지정한다.
                     plotName = paste0("65세_미만_총_소득_",y,"_년도") ) # paste0 는 여러개의 문자열을 서로 붙여주는 역할
      
      print(g)
      
      g_full <- append(g_full,g) #여러개의 지니계수를 배열 형태로 저장할 수 있음.
      
    }
    
    print(g_full)
    res = data.frame(year = 2007:2018,gini = g_full) # 결과
    print(res) # 결과 출력

     

     

    [소스 코드]

    ######## 최초 실행시 한번만 수행 ###########
    # install.packages("haven")
    # install.packages("dplyr")
    # install.packages("tidyr")
    # install.packages("ggplot2")
    # install.packages("labelled")
    # install.packages("reldist")
    # install.packages("lawstat")
    # install.packages("REAT")
    # install.packages("stringr")
    # install.packages("openxlsx")
    # install.packages("installr")
    ######## 최초 실행시 한번만 수행 ###########
    
    ######## 라이브러리 로드 ##############
    library(installr)
    installr::install.rtools()
    Sys.setenv(R_ZIPCMD= "C:/Rtools/bin/zip")
    # library(haven)
    library(dplyr)
    library(tidyr)
    library(ggplot2)
    library(foreign)
    library(labelled)
    library(reldist)
    library(lawstat)
    library(REAT)
    library(stringr)
    library(openxlsx)
    ######## 라이브러리 로드 ##############
    
    
    # sav 데이터 읽기
    #gini_sav_data <- read_spss("c:/workgini/gini_sav_data_Lnoin.sav") #경로는 임의로 변경 가능함
    gini_sav_data <- read_spss("./gini_sav_data_Lnoin.sav") #경로는 임의로 변경 가능함
    
    
    #컬럼이름 정하기
    colnames(gini_sav_data) <- c("year","h_reg5","h_reg7","h_din","h_cin","h01_1","h01_1s","h01_4","h01_11","h01_110",
                                 "ex_1","ex_2","ex_3","ex_4","ex_5","ex_6","ex_7","ex_8","ex_9",
                                 "total_living_expenses","total_expen_notax","earned_income","business_income","proberty_income",
                                 "etc_income","pub_pension","pri_pension","total_income","equalized_produc_income","equalized_income",
                                 "rank10","old","gen")  #컬럼은 임의로 변경 가능함
    
    # 추가 
    # 해당 명령어를 이용하여 데이터의 형태를 간략하게 조회해볼 수 있음 
    glimpse(gini_sav_data)
    
    
    # factor to character
    ## dbl+l 데이터가 존재하는 경우 이를 character로 만들기 위한 작업임 ##
    # dplyr::mutate(as.character(to_factor(컬림이름))...) 을 통해 변경 가능
    
    
    ## 수정사항 ##
    # to_factor 대신 as_factor 을 사용하여도 동일한 효과를 쓸 수 있음
    gini_sav_data_Lnoin <- gini_sav_data %>%
      dplyr::mutate(h_reg5 = as.character(as_factor(h_reg5)),
                    h_reg7 = as.character(as_factor(h_reg7)),
                    h01_4 = as.character(as_factor(h01_4)),
                    h01_110 = as.character(as_factor(h01_110)),
                    h01_11 = as.character(as_factor(h01_11)),
                    rank10 = as.numeric(rank10),
                    gen = as.numeric(gen))     
    
    ##### 컬럼 종류 #####
    
    # year : 조사년도
    # h_reg5 : 5개 권역별 지역구분
    # h_reg7 : 7개 전국지역 구분
    # h01_4 : 성별구분(1 남, 2 여) 
    # h01_110 : 가구형태
    # total_living_expenses : 총 생활비
    # old : 세대주 나이
    # earned_income : 근로소득
    # business_income : 사업소득
    # total_income : 전체소득
    # equalized_income : 균등화소득
    # rank10 : 10분위 구분 
    # gen : 일반, 노인세대 구분(2는 노인)
    
    ##### 컬럼 종류 #####
    
    ############## sav ##################
    
    
    
    ############ 데이터 읽기 및 가공종료 ##############
    
    
    ########################################### FUNCTION ###########################################
    giniValue <- function(data = data,income_col = income_col,plotFlag = FALSE,plotName = "result",plotPath = "./",...){
        
      addArg <- list(...)
    
      if(length(addArg) >= 1) {
        
       for (j in 1:length(addArg)) {
      
         nn <- as.data.frame(addArg[j])
         params <- data.frame(dum = c())
    
         if(nn[2,1] == "numeric"){ 
           
         for (k in 3:nrow(nn)) {
           param <- as.numeric(nn[k,1])
           params <- rbind(params,param)
         }
           
         } else if (nn[2,1] == "character") {
           
           for (k in 3:nrow(nn)) {
             param <- as.character(nn[k,1])
             params <- rbind(params,param)
           }
           
         } else {
           return("ERROR : 자료형의 입력이 잘못 되었습니다.")
         }
         
         # col name 재설정
         newColName = nn[1,1]
         colnames(params)[1] <- newColName
         # col name 재설정
         
         ### 데이터 필터링 ###
         data <- dplyr::inner_join(data,params,by=newColName)
         ### 데이터 필터링 ###
         
         # print(data)
         
         if(nrow(data) == 0) {
           return("조건에 맞는 데이터가 없습니다.")
         }
    
       }
       
      }
    
      # print(head(data))
      
      # 필터링된 데이터 선택 #
      x <- data[[income_col]]
      x_L1 <- sort(x)
      x_sum <- sum(x_L1)
      x_len <- length(x_L1)
      # 필터링된 데이터 선택 #
      
      # 지니계수 계산
      g = REAT::gini(x, lc = FALSE, lcx = "% of objects", 
                     lcy = "% of regarded variable", lctitle = "Lorenz curve", lcg = FALSE, 
                     lcgn = FALSE)
      
      
      # plotflag 여부에 따라 그림을 출력할지 말지 결정 #
      if(isTRUE(plotFlag)) {
        
      xx <- c()
      xy <- c()
      xw <- c()
      
      # x축 : 인구누적비율
      # y축 : 소득누적비율
      
      # 로렌츠 커브의 넓이를 계산하기 위한 코드
      tt <- 0
      
      for (i in 1:x_len) {
        
        isx <- i/x_len
        
        tt = tt+x_L1[i]
        
        isy <- tt/x_sum
        
        w <- (1/x_len) * isy
        
        xx <- append(xx,isx)
        xy <- append(xy,isy)
        xw <- append(xw,w)
        
      }
      # 로렌츠 커브의 넓이를 계산하기 위한 코드
      
      ############## w1 플로팅을 위한 위치좌표 설정  ############## 
      nis = seq(1,x_len,1)/x_len
      which_w1 = which.max(nis-xy)
      w1 = c(xx[which_w1],(nis[which_w1]+xy[which_w1])/2,0.5-round(sum(xw),4))
      ############## w1 플로팅을 위한 위치좌표 설정  ############## 
      
      # 결과를 데이터프레임에 저장
      res <- data.frame(x = xx, y = xy)
      
      ggplot(data = res) +
        theme_bw() +
        theme(text = element_text(size=14,face = "bold"),
              plot.title= element_text(size=18,face = "bold")) +
        geom_line(aes(x=xx,y=xy),size = 1.5,color = "blue") + 
        geom_text(aes(0.07, 0.97, label = paste0("G : ",round(g,4))),size = 5) +
        geom_text(aes(0.07, 0.92, label = paste0("N : ",length(x))),size = 5) +
        geom_text(aes(w1[1], w1[2], label = paste0("W1 = ",w1[3])),size = 5) +
        geom_abline(size = 1.5, color = "black") +
        # xlim(0,1) +
        # ylim(0,1) +
        xlab("인구 누적 비율") +
        ylab("소득 누적 비율") +
        labs(title = "gini value") +
        scale_x_continuous(expand = expansion(mult = c(0.01, 0.01)),breaks = c(0,0.25,0.5,0.75,1.0),limits = c(0,1)) +
        scale_y_continuous(expand = expansion(mult = c(0, 0)),breaks = c(0,0.25,0.5,0.75,1.0)) +
        ggsave(paste0(plotPath,plotName,".png"),dpi = 300,width = 8, height = 8)
      
      }
      
        # 지니계수 리턴
        return(g)
    
    }
    
    
    
    ###### 실제로 적용하는 예시 1 #########
    
    ## 조건 1 
    # 65세 이상 총 소득
    # 2007년부터 2018년까지
    
    # 비어있는 배열 생성
    g_full <- c()
    
    for (y in 2007:2018) {
      
      g <- giniValue(data = gini_sav_data_Lnoin,income_col = "total_income", # 총 소득
                     #param1 = c("year","numeric",y), # y를 대입 (2007 ~ 2018)
                     #param2 = c("old","numeric",over65old),
                     param3 = c("old","numeric",40), #65세 이상 (over65old)
                     plotFlag = TRUE,
                     plotPath = "C:\\tmpimg\\", # 이미지를 저장할 경로를 지정한다.
                     plotName = paste0("65세_이상_총_소득_",y,"_년도") ) # paste0 는 여러개의 문자열을 서로 붙여주는 역할
      
      print(g)
      
      g_full <- append(g_full,g) #여러개의 지니계수를 배열 형태로 저장할 수 있음.
      
      
    }
    
    print(g_full)
    res = data.frame(year = 2007:2018,gini = g_full) # 결과
    print(res) # 결과 출력
    
    ###### 실제로 적용하는 예시 1 #########
    
    
    ###### 실제로 적용하는 예시 2 #########
    
    ## 조건 2
    # 65세 미만 총 소득
    # 2007년부터 2018년까지
    
    # 비어있는 배열 생성
    g_full <- c()
    
    for (y in 2007:2018) {
      
      g <- giniValue(data = gini_sav_data_Lnoin,income_col = "total_income", # 총 소득
                     param1 = c("year","numeric",y), # y를 대입 (2007 ~ 2018)
                     param2 = c("old","numeric",under65old), #65세 미만 (under65old)
                     plotFlag = TRUE,
                     plotPath = "C:\\tmpimg\\", # 이미지를 저장할 경로를 지정한다.
                     plotName = paste0("65세_미만_총_소득_",y,"_년도") ) # paste0 는 여러개의 문자열을 서로 붙여주는 역할
      
      print(g)
      
      g_full <- append(g_full,g) #여러개의 지니계수를 배열 형태로 저장할 수 있음.
      
    }
    
    print(g_full)
    res = data.frame(year = 2007:2018,gini = g_full) # 결과
    print(res) # 결과 출력
    
    
    ###### 실제로 적용하는 예시 2 #########
    
    
    

     

    [결과물]

    • 지니계수 결과 이미지

     

     참고 문헌

    [논문]

    • 없음

    [보고서]

    • 없음

    [URL]

    • 없음

     

     문의사항

    [기상학/프로그래밍 언어]

    • sangho.lee.1990@gmail.com

    [해양학/천문학/빅데이터]

    • saimang0804@gmail.com
     
    반응형
    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기