R/Python (2) - 계산작업

2020/12/16

이 페이지는 컵활 1급의 Excel 예제를 그대로 R과 Python에서 해보는 것을 목적으로 하고 있습니다. 오류와 수정사항 그리고 교육문의는 으로 메일주시면 감사하겠습니다

이 시리즈는 유형2로 유형1을 놓치신 분들은 아래의 링크를 이용하시면 됩니다.

R/Python (1) - 기본작업

# R 코드입니다.
# Python 코드입니다.

필요한 패키지 준비

library(readxl) # read excel
library(dplyr)
library(DT)
library(formattable)

library(reticulate) # Python
#py_install(packages = "matplotlib")
#py_install(packages = "pandas")

유형2 - 계산작업

R

모든 예제 데이터 준비는 유형1과 같으므로 R/Python (1) 기본작업 을 참고하시면 되겠습니다.

예제2 데이터 준비

df2 = list_all[[2]]
new_header = df2[1,]
colnames(df2) = new_header
df2 = df2[2:10,] %>%
  mutate_at(vars(c(단가,할인율,원가비율,판매량,총매출)), as.numeric) %>%
  mutate_if(is.numeric,round, 3)
df2
## # A tibble: 9 x 9
##   제품코드 제품명 등급   판매량  단가 원가비율 평가  할인율 총매출
##   <chr>    <chr>  <chr>   <dbl> <dbl>    <dbl> <chr>  <dbl>  <dbl>
## 1 tv-a     <NA>   고급형     35  1200     0.7  <NA>    0.03     NA
## 2 tv-b     <NA>   중급형     60   800     0.6  <NA>    0.05     NA
## 3 tv-c     <NA>   보급형    120   600     0.55 <NA>    0.1      NA
## 4 vtr-b    <NA>   중급형     10   800     0.7  <NA>    0        NA
## 5 vtr-b    <NA>   고급형     34  1300     0.6  <NA>    0.03     NA
## 6 vtr-c    <NA>   보급형     60   800     0.55 <NA>    0.05     NA
## 7 aud-a    <NA>   고급형     25   600     0.7  <NA>    0        NA
## 8 aud-b    <NA>   중급형     54   800     0.6  <NA>    0.05     NA
## 9 aud-c    <NA>   고급형    110   500     0.55 <NA>    0.1      NA

계산 작업 (1)

  • 제품명은 제품코드 뒤의 두 글짜를 뺀 나머지이며, 대문자로 표시
df2_1 = 
  df2 %>%
  rowwise() %>%
  mutate('제품명' = substr(제품코드,1,(nchar(제품코드)-2))) %>%
  ungroup() %>%
  mutate('제품명' = toupper(.$제품명)) %>%
  #head(nrow(.)-1) %>%
  print()
## # A tibble: 9 x 9
##   제품코드 제품명 등급   판매량  단가 원가비율 평가  할인율 총매출
##   <chr>    <chr>  <chr>   <dbl> <dbl>    <dbl> <chr>  <dbl>  <dbl>
## 1 tv-a     TV     고급형     35  1200     0.7  <NA>    0.03     NA
## 2 tv-b     TV     중급형     60   800     0.6  <NA>    0.05     NA
## 3 tv-c     TV     보급형    120   600     0.55 <NA>    0.1      NA
## 4 vtr-b    VTR    중급형     10   800     0.7  <NA>    0        NA
## 5 vtr-b    VTR    고급형     34  1300     0.6  <NA>    0.03     NA
## 6 vtr-c    VTR    보급형     60   800     0.55 <NA>    0.05     NA
## 7 aud-a    AUD    고급형     25   600     0.7  <NA>    0        NA
## 8 aud-b    AUD    중급형     54   800     0.6  <NA>    0.05     NA
## 9 aud-c    AUD    고급형    110   500     0.55 <NA>    0.1      NA

계산 작업 (2)

  • 판매량이 큰 값부터 1위 ~ 3위는 “상”
  • 판매량이 큰 값부터 4위 ~ 6위는 “중”
  • 나머지 순위에 대해서는 “하”
df2_2 = 
  df2_1 %>%
  mutate_at(vars(판매량), funs(as.numeric)) %>%
  mutate('평가' =  
        ifelse(rank(-as.numeric(df2_1$판매량), ties.method = 'min') %in% 1:3, '상',
        ifelse(rank(-as.numeric(df2_1$판매량), ties.method = 'min') %in% 4:6, '중',
        '하'))) %>%
  print()
## Warning: `funs()` is deprecated as of dplyr 0.8.0.
## Please use a list of either functions or lambdas: 
## 
##   # Simple named list: 
##   list(mean = mean, median = median)
## 
##   # Auto named with `tibble::lst()`: 
##   tibble::lst(mean, median)
## 
##   # Using lambdas
##   list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.
## # A tibble: 9 x 9
##   제품코드 제품명 등급   판매량  단가 원가비율 평가  할인율 총매출
##   <chr>    <chr>  <chr>   <dbl> <dbl>    <dbl> <chr>  <dbl>  <dbl>
## 1 tv-a     TV     고급형     35  1200     0.7  중      0.03     NA
## 2 tv-b     TV     중급형     60   800     0.6  상      0.05     NA
## 3 tv-c     TV     보급형    120   600     0.55 상      0.1      NA
## 4 vtr-b    VTR    중급형     10   800     0.7  하      0        NA
## 5 vtr-b    VTR    고급형     34  1300     0.6  하      0.03     NA
## 6 vtr-c    VTR    보급형     60   800     0.55 상      0.05     NA
## 7 aud-a    AUD    고급형     25   600     0.7  하      0        NA
## 8 aud-b    AUD    중급형     54   800     0.6  중      0.05     NA
## 9 aud-c    AUD    고급형    110   500     0.55 상      0.1      NA

계산 작업 (3)

  • 판매량이 가장 큰 항목의 제품코드를 구하시오
df2_2$제품코드[which.max(df2_2$판매량)]
## [1] "tv-c"

계산 작업 (4)

  • 등급별 판매량의 합계를 구하시오
df2_2 %>%
  group_by(등급) %>%
  summarise('판매량 합계' = sum(판매량))
## # A tibble: 3 x 2
##   등급   `판매량 합계`
##   <chr>          <dbl>
## 1 고급형           204
## 2 보급형           180
## 3 중급형           124

계산 작업 (5)

  • 총매출을 계산할 사용자 정의함수를 만드시오.총매출은 단가(unit cost), 할인율(discount rate), 판매량(sales volume)을 인수로 받아 총매출을 계산하여 되돌려줌.
  • 총매출은 단가 x (1-할인율) x 판매량 으로 계산
cal_fun = function(unit_cost, discount_rate, sales_volumne){
  total = unit_cost * (1-discount_rate) * sales_volumne
}

df2_5 =
  df2_2 %>%
  mutate_at(vars(c(단가,할인율, 판매량)), funs(as.numeric)) %>%
  mutate('총매출' = cal_fun(단가, 할인율, 판매량)) %>%
  print()
## # A tibble: 9 x 9
##   제품코드 제품명 등급   판매량  단가 원가비율 평가  할인율 총매출
##   <chr>    <chr>  <chr>   <dbl> <dbl>    <dbl> <chr>  <dbl>  <dbl>
## 1 tv-a     TV     고급형     35  1200     0.7  중      0.03  40740
## 2 tv-b     TV     중급형     60   800     0.6  상      0.05  45600
## 3 tv-c     TV     보급형    120   600     0.55 상      0.1   64800
## 4 vtr-b    VTR    중급형     10   800     0.7  하      0      8000
## 5 vtr-b    VTR    고급형     34  1300     0.6  하      0.03  42874
## 6 vtr-c    VTR    보급형     60   800     0.55 상      0.05  45600
## 7 aud-a    AUD    고급형     25   600     0.7  하      0     15000
## 8 aud-b    AUD    중급형     54   800     0.6  중      0.05  41040
## 9 aud-c    AUD    고급형    110   500     0.55 상      0.1   49500

Python

Calling R from Python

We can access to R objects within Python cuhcks via the r object.

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

df = r.df2
df.head()
##     제품코드 제품명   등급    판매량      단가  원가비율  평가   할인율  총매출
## 0   tv-a  NA  고급형   35.0  1200.0  0.70  NA  0.03  NaN
## 1   tv-b  NA  중급형   60.0   800.0  0.60  NA  0.05  NaN
## 2   tv-c  NA  보급형  120.0   600.0  0.55  NA  0.10  NaN
## 3  vtr-b  NA  중급형   10.0   800.0  0.70  NA  0.00  NaN
## 4  vtr-b  NA  고급형   34.0  1300.0  0.60  NA  0.03  NaN

계산 작업 (1)

  • 제품명은 제품코드 뒤의 두 글짜를 뺀 나머지이며, 대문자로 표시
df2_1 = df.copy()
df2_1['제품명'] = df2_1['제품코드'].apply(lambda x: x[:-2]).str.upper()
df2_1
##     제품코드  제품명   등급    판매량      단가  원가비율  평가   할인율  총매출
## 0   tv-a   TV  고급형   35.0  1200.0  0.70  NA  0.03  NaN
## 1   tv-b   TV  중급형   60.0   800.0  0.60  NA  0.05  NaN
## 2   tv-c   TV  보급형  120.0   600.0  0.55  NA  0.10  NaN
## 3  vtr-b  VTR  중급형   10.0   800.0  0.70  NA  0.00  NaN
## 4  vtr-b  VTR  고급형   34.0  1300.0  0.60  NA  0.03  NaN
## 5  vtr-c  VTR  보급형   60.0   800.0  0.55  NA  0.05  NaN
## 6  aud-a  AUD  고급형   25.0   600.0  0.70  NA  0.00  NaN
## 7  aud-b  AUD  중급형   54.0   800.0  0.60  NA  0.05  NaN
## 8  aud-c  AUD  고급형  110.0   500.0  0.55  NA  0.10  NaN

계산 작업 (2)

  • 판매량이 큰 값부터 1위 ~ 3위는 평가 “상”
  • 판매량이 큰 값부터 4위 ~ 6위는 평가 “중”
  • 나머지 순위에 대해서는 평가 “하”
df2_2 = df2_1.copy()
df2_2['평가'] =  (-df2_2['판매량']).rank(method='min').apply(
                      lambda x: '상' if x in range(1,4) else 
                                  '중'  if x in range(4,7) else
                                    '하')
df2_2

# def rank(data):
#   return np.array([sorted(data).index(x) for x in df2_2['판매량']])
# np.isin(rank(df2_2['판매량']),range(1,4))
##     제품코드  제품명   등급    판매량      단가  원가비율 평가   할인율  총매출
## 0   tv-a   TV  고급형   35.0  1200.0  0.70  중  0.03  NaN
## 1   tv-b   TV  중급형   60.0   800.0  0.60  상  0.05  NaN
## 2   tv-c   TV  보급형  120.0   600.0  0.55  상  0.10  NaN
## 3  vtr-b  VTR  중급형   10.0   800.0  0.70  하  0.00  NaN
## 4  vtr-b  VTR  고급형   34.0  1300.0  0.60  하  0.03  NaN
## 5  vtr-c  VTR  보급형   60.0   800.0  0.55  상  0.05  NaN
## 6  aud-a  AUD  고급형   25.0   600.0  0.70  하  0.00  NaN
## 7  aud-b  AUD  중급형   54.0   800.0  0.60  중  0.05  NaN
## 8  aud-c  AUD  고급형  110.0   500.0  0.55  상  0.10  NaN

계산 작업 (3)

  • 판매량이 가장 큰 항목의 제품코드를 구하시오
df2_2['제품코드'] [df2_2['판매량'].argmax()]
## 'tv-c'

계산 작업 (4)

  • 등급별 판매량의 합계를 구하시오
df2_2.groupby('등급').sum()['판매량']
## 등급
## 고급형    204.0
## 보급형    180.0
## 중급형    124.0
## Name: 판매량, dtype: float64

계산 작업 (5)

  • 총매출을 계산할 사용자 정의함수를 만드시오.총매출은 단가(unit cost), 할인율(discount rate), 판매량(sales volume)을 인수로 받아 총매출을 계산하여 되돌려줌.
  • 총매출은 단가 x (1-할인율) x 판매량 으로 계산
def cal_fun(unit_cost, discount_rate, sales_volume):
  return unit_cost * (1-discount_rate) * sales_volume

df2_2['총매출'] = df2_2.apply(lambda x: cal_fun(x['단가'],x['할인율'],x['판매량']), axis=1)
df2_2
##     제품코드  제품명   등급    판매량      단가  원가비율 평가   할인율      총매출
## 0   tv-a   TV  고급형   35.0  1200.0  0.70  중  0.03  40740.0
## 1   tv-b   TV  중급형   60.0   800.0  0.60  상  0.05  45600.0
## 2   tv-c   TV  보급형  120.0   600.0  0.55  상  0.10  64800.0
## 3  vtr-b  VTR  중급형   10.0   800.0  0.70  하  0.00   8000.0
## 4  vtr-b  VTR  고급형   34.0  1300.0  0.60  하  0.03  42874.0
## 5  vtr-c  VTR  보급형   60.0   800.0  0.55  상  0.05  45600.0
## 6  aud-a  AUD  고급형   25.0   600.0  0.70  하  0.00  15000.0
## 7  aud-b  AUD  중급형   54.0   800.0  0.60  중  0.05  41040.0
## 8  aud-c  AUD  고급형  110.0   500.0  0.55  상  0.10  49500.0