아래 링크를 따라 해 보았습니다.
>> medium.com/@gscheithauer/process-mining-in-10-minutes-with-r-1ab28ed74e81

 

1. 들어가기 전에

프로세스 마이닝은 프로세스 분석을 하는 것이고 워크숍, 인터뷰, 과거 문서들이 아닌 비즈니스 시스템에서 도출된 데이터를 기반으로 프로세스 마이닝을 적용시킬 수도 있죠! 프로세스 모델을 생성하고 이 모델을 활용해 프로세스 준수 문제를 발견할 수도 있습니다. 현재 프로세스 마이닝을 할 수 있는 많은 도구가 있지만 그중 하나인 오픈 소스 도구인 buparR(여러 R 패키지로 구성됨)을 이용합니다.

2. 데이터 소개 및 준비하기

이 글에서는 BPI Challenge 2017 [5]에서 제공 한 은행 신용 응용 프로그램 프로세스의 실제 데이터(익명)를 사용합니다. 분석 전 아래 깃 레포지토리를 다운로드합니다.
>> Clone GitHub project: https://github.com/scheithauer/processmining-bupaR

 

scheithauer/processmining-bupaR

Process Mining with bupaR. Contribute to scheithauer/processmining-bupaR development by creating an account on GitHub.

github.com

3. 분석

분석이지만 남의 코드 뜯어보기!! (다운로드한 레포에서 01-scripts 폴더의 00_pm_bupar_MAIN.R을 열어주세요!)

3.1 패키지 설치하기

이 분은 벡터 표시 (c)를 앞에 붙여주는군요! 추가적으로 namespace 'htmltools' 0.4.0 is being loaded, but >= 0.4.0.9003 is required 에러가 난다면.. 업데이트를 해도 똑같다면 그냥.. R을 지우고 새로 설치하세요.. 4 버전으로... 그럼 해결이 됩니다.. 

# check installed packages and install only necessary ones #### 
c_necessary_packages <- c( 
  'bupaR', 
  'edeaR', 
  'processmapR', 
  'eventdataR', 
  'readr', 
  'tidyverse', 
  'DiagrammeR', 
  'ggplot2', 
  'stringr', 
  'lubridate'   
) 
c_missing_packages <- c_necessary_packages[!(c_necessary_packages %in% installed.packages()[,"Package"])] 
if(length(c_missing_packages) > 0) install.packages(c_missing_packages)

3.2 패키지 불러오기

자 패키지를 설치했으면 설치한 패키지들을 불러야겠죠?

library(bupaR)
library(edeaR)
library(processmapR)
library(eventdataR)
library(readr)
library(tidyverse)
library(DiagrammeR)
library(ggplot2)
library(stringr)
library(lubridate)

3.3 데이터 불러오기

자 이제 데이터들도 읽어봅시다.

# load BPI Challenge 2017 data set ####
data <- readr::read_csv('./00-data/loanapplicationfile.csv',
                         locale = locale(date_names = 'en',
                                         encoding = 'ISO-8859-1'))

# change timestamp to date var
data$starttimestamp = as.POSIXct(data$`Start_Timestamp`, 
                                 format = "%Y/%m/%d %H:%M:%S")

data$endtimestamp = as.POSIXct(data$`Complete_Timestamp`, 
                               format = "%Y/%m/%d %H:%M:%S")

# remove blanks from var names
names(data) <- str_replace_all(names(data), c(" " = "_" , "," = "" ))

3.4 이벤트 로그로 변경하기

프로세스 마이닝을 적용하기 위해 데이터를 이벤트 로그로 변환합니다.

# transform data into eventlog
events <- bupaR::activities_to_eventlog(
  data,
  case_id = 'Case_ID',
  activity_id = 'Activity',
  resource_id = 'Resource',
  timestamps = c('starttimestamp', 'endtimestamp')
)

참고: 이벤트 로그 변환 관련 bupaR

3.5 데이터 탐색하기

# statistics eventlog ####
events %>% 
  summary

events %>% 
  activity_frequency(level = "activity") 

events %>% 
  activity_frequency(level = "activity") %>% 
  plot()


# filter all cases where one specific activity was present
events %>% 
  filter_activity_presence(activities = c('A_Cancelled')) %>% 
  activity_frequency(level = "activity") 

 

3.6 프로세스 마이닝

# process map ####
events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  process_map(render = F) %>% 
  export_graph(file_name = './02-output/01_pm-bupar_process map.png',
               file_type = 'PNG')


# process map - performance ####
events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  process_map(performance(mean, "mins"),
              render = F) %>% 
  export_graph(file_name = './02-output/02_pm-bupar_process map performance.png',
               file_type = 'PNG')


# precedent matrix ####
precedence_matrix <- events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  precedence_matrix() %>% 
  plot()

ggsave('./02-output/03_pm-bupar_process precedence matrix.png', precedence_matrix)
rm(precedence_matrix)


# trace explorer
trace_explorer <- events %>%
  trace_explorer(coverage = 0.5)

ggsave('./02-output/04_pm-bupar_trace explorer.png', trace_explorer, width = 12)
rm(trace_explorer)

# idotted chart
chart <- events %>%
  dotted_chart()

chart

# resource map ####
events %>%
  filter_activity_frequency(percentage = .1) %>% # show only most frequent resources
  filter_trace_frequency(percentage = .8) %>%    # show only the most frequent traces
  resource_map(render = F) %>% 
  export_graph(file_name = './02-output/05_pm-bupar_resource map.png',
               file_type = 'PNG')


# resource matrix ####
resource_matrix <- events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  resource_matrix() %>% 
  plot()

ggsave('./02-output/06_pm-bupar_resource matrix.png', resource_matrix)
rm(resource_matrix)


# process map where one activity was at least once present ####
events %>%
  filter_activity_presence(activities = c('A_Cancelled')) %>% 
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  process_map(render = F) %>% 
  export_graph(file_name = './02-output/07_pm-bupar_process map cancelled.png',
               file_type = 'PNG')


# process map where one activity was at least once present in Feb 2016 ####
events %>%
  filter_time_period(interval = c(ymd(20160101), end_point = ymd(20160102)),
                     filter_method = 'start') %>% 
  filter_activity_presence(activities = c('A_Cancelled')) %>% 
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  process_map(render = F) %>% 
  export_graph(file_name = './02-output/08_pm-bupar_process map cancelled time intervall.png',
               file_type = 'PNG')


# Conditional Process Analysis ####
events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  throughput_time('log', units = 'hours')

events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  throughput_time('case', units = 'hours')

  
events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  group_by(`(case)_ApplicationType`) %>% 
  throughput_time('log', units = 'hours')
  
plot <- events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  group_by(`(case)_ApplicationType`) %>% 
  throughput_time('log', units = 'hours') %>% 
  plot()

plot

ggsave('./02-output/08_pm-bupar_throughput application type.png', plot)
rm(plot)

events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  group_by(`(case)_LoanGoal`) %>% 
  throughput_time('log', units = 'hours')

plot <- events %>%
  filter_activity_frequency(percentage = 1.0) %>% # show only most frequent activities
  filter_trace_frequency(percentage = .80) %>%    # show only the most frequent traces
  group_by(`(case)_LoanGoal`) %>% 
  throughput_time('log', units = 'hours') %>% 
  plot()

plot

ggsave('./02-output/09_pm-bupar_throughput loan goal.png', plot)
rm(plot)

 

음.. 따라 해 보았지만 여전히 뭔 말인지 모르겠다. 다음부터는 bupaR 함수 하나하나 봐야겠다.

오랜만에 R을 써서 그런지 많은 함수와.. 사용법을 잊어버렸다.. 이것은 파이썬 덕분....... 따라서 이를 정리해본다.

1. 데이터 불러오기

먼저 readr 패키지로 csv 파일을 불러오자.

library(readr)

root_path <- 'C:\\Users\\LG\\Desktop\\data_set'
df <- read_csv(file.path(root_path, 'word.csv'))

출력 결과이다.

Parsed with column specification:
cols(
  id = col_double(),
  sex = col_double(),
  bday = col_date(format = ""),
  overall = col_double(),
  supervisor = col_double(),
  conditions = col_double(),
  colleagues = col_double(),
  workplace = col_double(),
  tasks = col_double()
)
> df
# A tibble: 50 x 9
      id   sex bday       overall supervisor conditions colleagues workplace tasks
   <dbl> <dbl> <date>       <dbl>      <dbl>      <dbl>      <dbl>     <dbl> <dbl>
 1     1     1 1999-08-04      65         47         53         74        49    54
 2     2     0 2000-01-16      58         79         73         72        41    46
 3     3     1 1999-07-16       0         32         10         25         9    30
 4     4     0 1999-09-03      80         53         71         67        52    37
 5     5     1 1999-05-22      56         52         21         31        50    46
 6     6     0 1999-10-19      93         92         45         80       100    77
 7     7     1 2000-02-05      45         57         44         55        19    47
 8     8     1 1998-08-01      61         63         77         81        63    49
 9     9     0 2000-01-09      68         63         49         76        39    99
10    10     0 1999-09-19      71         66         69         81        53    62
# ... with 40 more rows

2. 컬럼 추가

성별이 0일 경우 여성, 성별이 1일 경우 남성으로 나타낸 컬럼을 추가해본다.

먼저 dplyr 패키지를 설치한다.

install.packages("dplyr")

이제 데이터 프레임에 컬럼을 추가해보자. 컬럼 생성은 mutate() 함수를 사용한다. 함수 사용시 mutate(새로 생성할 컬럼명 = 값/조건)으로 입력하는데 이 때, 조건일 경우 조건 설정에 if_else, case_when 2가지 방법을 사용할 수 있다.

library(dplyr)

buff = 0
if(buff == 0) {
  new_df <- df %>%
    mutate(sex_desc = if_else(sex == 0, 'Female', 'Male'))
} else {
  new_df <- df %>%
    mutate(sex_desc = case_when(sex == 0 ~ 'Female',
                                TRUE ~ 'None'))
}
new_df

컬럼 추가 결과이다.

> new_df
# A tibble: 50 x 10
      id   sex bday       overall supervisor conditions colleagues workplace tasks sex_desc
   <dbl> <dbl> <date>       <dbl>      <dbl>      <dbl>      <dbl>     <dbl> <dbl> <chr>   
 1     1     1 1999-08-04      65         47         53         74        49    54 male    
 2     2     0 2000-01-16      58         79         73         72        41    46 Female  
 3     3     1 1999-07-16       0         32         10         25         9    30 male    
 4     4     0 1999-09-03      80         53         71         67        52    37 Female  
 5     5     1 1999-05-22      56         52         21         31        50    46 male    
 6     6     0 1999-10-19      93         92         45         80       100    77 Female  
 7     7     1 2000-02-05      45         57         44         55        19    47 male    
 8     8     1 1998-08-01      61         63         77         81        63    49 male    
 9     9     0 2000-01-09      68         63         49         76        39    99 Female  
10    10     0 1999-09-19      71         66         69         81        53    62 Female  

그런데 혹시라도 3, 4 등과 같은 이상치가 발생될 수 있으므로 조건을 정확히 설정하고 예외 숫자를 다르게 표현할 수 있게 하는 것을 추천한다. 아래는 case_when을 사용한 예제이다. (이 때, 0일 때는 여성, 1일 때는 남성, 나머지는 None으로 처리한다.)

new_df <- df %>%
  mutate(sex_desc = case_when(sex == 0 ~ 'Female',
                              sex == 1 ~ 'male',
                                TRUE ~ 'None'))

4. 컬럼 순서 재정렬하기

이제 새롭게 생성된 컬럼를 성별 바로 뒤로 올 수 있도록 컬럼 재정렬을 해본다.
직접 컬럼 벡터 사용, select()함수를 사용하는 2가지 방법으로 컬럼을 재정렬할 수 있다.
**위 2가지 방법 모두 컬럼명을 이용해 재졍렬 순서를 입력하면 된다.

# library(dplyr)
buff = 0
if(buff == 0) {
  new_columns_order = c('id', 'sex', 'sex_desc', 'bday',
                        'overall', 'supervisor', 'conditions',
                        'colleagues', 'workplace', 'tasks')
  new_df <- new_df[new_columns_order]
} else {
  new_df <- new_df %>%
    select(id, sex, sex_desc, bday,
           overall, supervisor, conditions,
           colleagues, workplace, tasks)
}
new_df

아래는 재정렬된 결과이다.

> new_df
# A tibble: 50 x 10
      id   sex sex_desc bday       overall supervisor conditions colleagues workplace tasks
   <dbl> <dbl> <chr>    <date>       <dbl>      <dbl>      <dbl>      <dbl>     <dbl> <dbl>
 1     1     1 male     1999-08-04      65         47         53         74        49    54
 2     2     0 Female   2000-01-16      58         79         73         72        41    46
 3     3     1 male     1999-07-16       0         32         10         25         9    30
 4     4     0 Female   1999-09-03      80         53         71         67        52    37
 5     5     1 male     1999-05-22      56         52         21         31        50    46
 6     6     0 Female   1999-10-19      93         92         45         80       100    77
 7     7     1 male     2000-02-05      45         57         44         55        19    47
 8     8     1 male     1998-08-01      61         63         77         81        63    49
 9     9     0 Female   2000-01-09      68         63         49         76        39    99
10    10     0 Female   1999-09-19      71         66         69         81        53    62

5. 데이터 저장하기

아래 코드는 저번 포스트와 동일

#library(readr)
write_csv(new_df, file.path(root_path, 'word_add_sex_desc.csv'))

'R > 기본' 카테고리의 다른 글

R로 .csv 형식 저장하기  (0) 2020.06.06
R로 .sav 파일 읽기  (0) 2020.06.06

readr 패키지를 사용하여 데이터 프레임을 .csv 파일로 저장해본다.

1. 패키지 설치

install.packages("readr")

2. .csv/.tsv로 저장하기

write_csv(쉼표 구분) 말고도 write_delim() 함수를 사용하면 delimeter를 직접 선정할 수 있다.
이 때, delimeter는 반드시 한 개로 해야 한다.

library(readr)

root_path <- 'C:\\Users\\LG\\Desktop\\data_set'
write_csv(df, file.path(root_path, 'word.csv'))
write_tsv(df, file.path(root_path, 'word.tsv'))

참고

https://readr.tidyverse.org/reference/write_delim.html

'R > 기본' 카테고리의 다른 글

data-frame에 컬럼 추가/정렬하기  (0) 2020.06.06
R로 .sav 파일 읽기  (0) 2020.06.06

.sav를 읽을 수 있게 하는 패키지는 많이 존재하지만 haven 패키지는 tidyverse에서 소개했기 때문에 이 패키지를 사용하기로 결정했다.

1. 패키지 설치

install.packages("haven")

2. 패키지 사용한 .sav 파일 읽기

haven 패키지의 함수 read_sav() 사용

library(haven)

root_path = 'C:\\Users\\LG\\Desktop\\data_set'
file_name = 'work.sav'
full_path = file.path(root_path, file_name)
df = read_sav(full_path)
df

3. 결과 확인

> df
# A tibble: 50 x 9
      id        sex bday                     overall supervisor conditions colleagues           workplace     tasks
   <dbl>  <dbl+lbl> <date>                 <dbl+lbl>  <dbl+lbl>  <dbl+lbl>  <dbl+lbl>           <dbl+lbl> <dbl+lbl>
 1     1 1 [Male]   1999-08-04 65                            47         53         74  49                        54
 2     2 0 [Female] 2000-01-16 58                            79         73         72  41                        46
 3     3 1 [Male]   1999-07-16  0 [Totally disagree]         32         10         25   9                        30
 4     4 0 [Female] 1999-09-03 80                            53         71         67  52                        37
 5     5 1 [Male]   1999-05-22 56                            52         21         31  50                        46
 6     6 0 [Female] 1999-10-19 93                            92         45         80 100 [Totally agree]        77
 7     7 1 [Male]   2000-02-05 45                            57         44         55  19                        47
 8     8 1 [Male]   1998-08-01 61                            63         77         81  63                        49
 9     9 0 [Female] 2000-01-09 68                            63         49         76  39                        99
10    10 0 [Female] 1999-09-19 71                            66         69         81  53                        62

위에서 데이터 옆 대괄호 내용은 SPSS의 변수보기 탭의 '값'열에 해당한다.

참고

https://cran.r-project.org/web/packages/haven/haven.pdf

'R > 기본' 카테고리의 다른 글

data-frame에 컬럼 추가/정렬하기  (0) 2020.06.06
R로 .csv 형식 저장하기  (0) 2020.06.06

'R' 카테고리의 다른 글

정규식 관련  (0) 2019.04.18

'R' 카테고리의 다른 글

RstudioGD?  (0) 2019.04.22

+ Recent posts