3 분 소요

간단한 예제를 R을 통하여 알아본다

데이터 설명

  • 기존데이터 : 기존에 근무하는 직원의 데이터 이다.

    age job_area education income
    30 accounting 12 50
    34 marketing 16 60
    47 accounting 18 70
    55 accounting 12 55
    35 mis 16 58
    42 accounting 18 70
    47 mis 12 45
  • 신규채용자 : 신규로 들어 오는 직원의 정보인데, 소득을 정하고자 하는 예제 이다.

    age job_area education income
    39 mis 14 55

R코드 설명

  • 거리및 유사도를 구하는 사용자 정의 함수

    
    # 거리 정의 및 유사도를 구하는 사용자 정의 함수
    # 사용법은 weight와 구하고자 하는 거리인덱스, 원래데이터, 신규데이터 를 정해 주면 됨
    
    dist = function (o_data,n_data, col_name ) { 
    
    
        wg = wg_list[[paste('wg', col_name , sep='_')]]
        #등록하지 않는 가중치는 0으로 셋
        if( is.null(wg) ) {  
          wg = 0
        }
    
        if( class(o_data) == "numeric" || class(o_data) == "integer" ) {
          return ( wg * abs(o_data - n_data)/max(o_data) )
        } else if( class(o_data) == "character" ) {
          return ( ifelse(o_data == n_data, 0,1) )
        } else {
          return ( o_data )
        }
    }
    
    cbrUsrFunction = function (oldData, newData , distRange) { 
        
      #거리를 구하지 않는 변수는 맨 마직으로 세팅해야 한다.
        
      dl = list()
        
      #마지막 Target
      for ( k in 1:ncol(oldData) ) {
          
        ret_x = c()
        ret_y = c()
        y_idx = c()
        x_idx = c()    
          
        for( i in 1:nrow(oldData[k]) ) {
          for( j in 1:nrow(newData[k]) ) {
              
              ret_x = c( ret_x, oldData[i,k])  #paste("o",i,"n",j)
              ret_y = c( ret_y, newData[j,k])
              x_idx = c( x_idx, paste("o",i , sep= "") )
              y_idx = c( y_idx, paste("n",j , sep= "") )
          }
        }
          
        #제외변수는 는 거리를 구하지 않음
        if (k %in% distRange ) {    
          ret_dist = dist(ret_x,ret_y, colnames(oldData[k])  )
          dl = cbind(dl, ret_x, ret_y, ret_dist)
          colnames(dl)[which(colnames(dl) == "ret_x")] = paste("x",colnames(oldData[k]))
          colnames(dl)[which(colnames(dl) == "ret_y")] = paste("y",colnames(oldData[k]))    
          colnames(dl)[which(colnames(dl) == "ret_dist")] = paste("diff",colnames(oldData[k]))  
        } else { 
          dl = cbind(dl, ret_x, ret_y)
          colnames(dl)[which(colnames(dl) == "ret_x")] = paste("x",colnames(oldData[k]))
          colnames(dl)[which(colnames(dl) == "ret_y")] = paste("y",colnames(oldData[k]))    
        }
        
      }
        
      df = data.frame(dl)
        
      # numeric,character 등 변환 이 반드시 필요 및 diff 
      # 거리는 모두 numeric
        
      ran = ( distRange ) * 3
      for ( k in ran ) {
          
        if ( class(oldData[,k/3]) == "numeric" ) {
            df[,k-2] = as.numeric( df[,k-2] )      
            df[,k-1] = as.numeric( df[,k-1] )
            df[,k] = as.numeric( df[,k] )
        }
        if ( class(oldData[,k/3]) == "integer" ) {
          df[,k-2] = as.integer( df[,k-2] )      
          df[,k-1] = as.integer( df[,k-1] )
          df[,k] = as.numeric( df[,k] )
        }
        if ( class(oldData[,k/3]) == "character" ) {
          df[,k-2] = as.character( df[,k-2] )      
          df[,k-1] = as.character( df[,k-1] )
          df[,k] = as.numeric( df[,k] )
        }
    
      }
        
      #마지막컬럼 Target 변경
      if( class( oldData[,ncol(oldData)] ) == "integer") {
        df[,ncol(df)] = as.integer( df[,ncol(df)] )      
        df[,ncol(df)-1] = as.integer( df[,ncol(df)-1] )
      }
        
        
      # Total distance 구하기
      df[,ran] %>% rowSums(na.rm=TRUE) -> df$diff.total
        
      # Simularity 구하기  1 / (1+dist)
      df$Simularity = 1 / (1+df$diff.total)
        
      # Old, new 인덱스 붙이기
      df$x_idx = x_idx 
      df$y_idx = y_idx
        
      df$sel_sim = "-"
        
      # 최고유사선택
        
      for( j in 1:nrow(newData) ) {
        col = paste("n",j , sep= "")
        subdf = df[df$y_idx==col,]
        idx = which.max( subdf[,"Simularity"] )
        yidx = subdf[idx,'y_idx']
        xidx = subdf[idx,'x_idx']
        df[ df$y_idx==yidx & df$x_idx==xidx, 'sel_sim' ] = 'bestSimularity'
          
      }
    
      return ( df )
    }
    
    
  • CBR 분석 진행

    # Case based Reasoning
    
    # 1) Old Case Read
    > oCR = read.csv('old_data.csv', header = T , stringsAsFactors=F )
    # 2) New Case read
    > nCR = read.csv('new_data.csv', header = T , stringsAsFactors=F )
    # 3) 가중치 부여 - wg_ 뒤에 헤더이름을 맞추면 됨
    > wg_list = list(wg_age=1, wg_job_area=0.15, wg_education=1.5)
    
    # 4) 거리를 구하고자 하는 변수의 순서 결정 ( Cbr에 대한 사용자 함수를 사용하기 위해 )
    > getDistVar = c(1,2,3)  #age, job_area, education 3가지 변수로 소득을 결정 하기 위해 컬럼 인덱스 지정
    
    # 5) 거리및 유사도 계산
    > df = cbrUsrFunction(oCR, nCR , getDistVar)
    
    # 6) 결과
    df[df$sel_sim=='bestSimularity', c(which(colnames(df)=="x.age") , which(colnames(df)=="x.job_area") , which(colnames(df)=="x.education"), which(colnames(df)=="x.income")  , which(colnames(df)=="x_idx") ) ]
    
  • 실행결과

      x.age x.job_area x.education x.income x_idx
    5    35        mis          16       58    o5
    

    가장 유사한 현재 직원의 경우 5번째 직원으로 소득이 58 수준이다. 따라서 신규 직원도 이를 감안 해서 결정 해야한다고 볼 수 있다.

댓글남기기