포스팅은 아래 영문 블로그의 코드를 구현해보고 , 내용을 요약 발췌하여 작성함을 알려드립니다.

따라서 포스팅에 올려지는 모든 그림과 도표 등의 내용은 아래 영문 링크를 들어가셔도 동일하게 보실 있습니다.


Part 1에서 indeed API의 데이터 과학자 및 데이터 분석가 포지션의 정보를 수집하고, jobbR 패키지를 이용해서 간단한 정보비교를 해보았습니다. 
급여는 데이터 과학자가 분석가에 비해 많이 받는것을 알게 되었습니다. 급여 격차를 감안할때 , 각 직군이 요구하는 직무의 차이를 확인할수 있을까요?
만약 가능하다면, 데이터 과학자 역할을 직무설명으로 부터 추출해서 무엇인지를 예측할수 있을까요? 본 포스팅은 이부분을 간단한 자연어 처리를 이용해서 확인해보는 것으로 진행해보도록 하겠습니다. 


데이터 수집

데이터 추출은 part1에서 하였던 것과 유사하게 진행합니다. Indeed API에서 런던의 모든 데이터 과학자 및 데이터 분석가 작업을 추출한다음 , 주니어와 시니어 포지션을 걸러내고 남은 부분을 분석합니다.
본질적으로 part1의 반복이므로 많은 고민을 하지 않고 바로 처리할수 있습니다. 

>install.packages("devtools")
>library(devtools)
>install_github("dashee87/jobbR")
>install.packages("plotly")
>install.packages("dplyr")

우선 아래 코드를 직접 확인하기 위해서는  위와같이 R studio에 입력하여서 패키지를 설치하여야 합니다.


## if you haven't already installed jobbR
# devtools::install_github("dashee87/jobbR")
## loading the packages we'll need

 library(jobbR)
 library(dplyr)
 library(rvest)
 library(stringr)
 library(plotly)

# collecting data scientist jobs from the Indeed API
dataScientists <- jobSearch(publisher = "publisherkey", query = "data+scientist", country = "uk", location = "london", all = TRUE)

# collecting data analyst jobs from the Indeed API
dataAnalysts <- jobSearch(publisher = "publisherkey", query =  "data+analyst", country = "uk", location = "london", all = TRUE)

# removing junior and senior roles
dataScientists <- dataScientists[grepl(
  "data scientist", dataScientists$results.jobtitle,ignore.case = TRUE) &
    !grepl("senior|junior|lead|manage|intern|analyst|graduate|chief",
          dataScientists$results.jobtitle,ignore.case = TRUE),]

dataAnalysts <- dataAnalysts[grepl(
  "data analyst", dataAnalysts$results.jobtitle,ignore.case = TRUE) &
    !grepl("senior|junior|lead|manage|intern|scientist|graduate|chief",
          dataAnalysts$results.jobtitle,ignore.case = TRUE),]

dataScientists <- dataScientists[!duplicated(dataScientists$results.jobkey),]
dataAnalysts <- dataAnalysts[! duplicated(dataAnalysts$results.jobkey),]

install.packages("selectr")
library("selectr")

# scrape job description webpages
ds_job_descripts <- unlist(lapply(dataScientists$results.url,
                              function(x){read_html(x) %>%
                                  html_nodes("#job_summary") %>%
                                  html_text() %>% tolower()}))

da_job_descripts <- unlist(lapply(dataAnalysts$results.url,
                                  function(x){read_html(x) %>%
                                      html_nodes("#job_summary") %>%
                                      html_text() %>% tolower()}))

위의 내용을 실행하시면, 두개의 직무기술서에 대한 벡터를 얻을수 있습니다. 하나의 벡터 내에 있는 element는 단지 여러줄의 단어 나열이나 문장들로 구성되어 있습니다.


# an example data scientist job description
# I picked 49 as it's one of the shorter ones
ds_job_descripts[49]


# [1] "data scientist, python x2\ncentral london\n\n£doe\n\ndata scientists are required by a leading data insights company, based in the city.\n\nthese data scientist opportunities requires those who are able to perform early stage research and development for our clients internal data, in order to help perform discovery and proof of concept in house.\n\nalong with these data scientist positions you<U+0092>ll be expected to design and build software products in python and sql. those who are able to provide a generous like for like comparison will prove highly successful in their application. any agile experience will also be a huge advantage.\n\nto apply for these data scientist roles please send your cv to imogen morpeth at arc it recruitment or call for a consultation\n\ndata scientist, python, sql, proof of concept, data driven research, data stories, numpy, scikit-learn, matplotlib, pandas, statsmodels, seaborn"

위와같이 하나의 element를 뽑아서 보면 단순한 문장과 단어들로 구성되어 있어서 이것을 직접적으로 분석하기에는 무리가 있습니다. 

따라서 여기에서 인사이트를 얻고자 한다면 우리는  bag-of-words 모델을 이용하야합니다. 



간단히 설명하면, 문자열을 특정 관심 단어로 줄이고 각문자열에서 각 단어의 수를 계산합니다. 따라서 이것을 하기 위해 특정 관심단어를 정해야 합니다. 
여기서는 skill이라는 데이터 프레임을 만들었기 때문에 skill내에 존재하는 요소를 48개로 정리해보았습니다. 이것을 아래와 같이 
title에 정리하였고, regex ( regular expression) 는 title에 정리한 열과 유사한 설명들을 적어놓았습니다. 그리하여 regex에 포함된 단어들이 발견되었을 경우에는 
title에 정리된 단어로 count할수 있게끔 정리를 한것입니다. 예를 들면 math는 maths혹은 mathematics와 동일한 것으로 보고 count를 하게끔 한 것입니다.


skills=data.frame(
  title=c("R", "Python", "SQL", "Excel", "Powerpoint", "KPI", "Dashboard",
          "Matlab", "Tableau", "Qlikview", "D3", "SAS", "SPSS", "BI", "C++",
          "Java", "Javascript", "Ruby", "Scala", "Php", "VBA",
          "Machine Learning", "Big Data", "Modelling", "Communication",
          "Stakeholder", "Masters", "PhD", "Hadoop", "Spark", "Map Reduce",
          "Pig", "Hive", "NoSQL", "MongoDB", "Cassandra", "Mahout",
          "Google Analytics", "Adobe", "API", "NLP", "Maths", "Statistics",
          "Physics", "Computer Science", "Engineering", "Economics",
          "Finance"),
  regex=c("r", "python|numpy|pandas|scikit", "sql|mysql|sql server|mssql",
          "excel","powerpoint|power point", "dashboards?", "kpis?",
          "matlab", "tableau", "qlikview", "d3", "sas", "spss",
          "bi|business intelligence", "c\\+\\+|c/c\\+\\+", "java",
          "javascript", "ruby", "scala", "php", "vba?|visual basic",
          "machine learning", "big data", "modelling|modeling",
          "communication", "stakeholders?", "masters?|msc","phd", "hadoop",
          "spark", "map reduce|mapreduce|map/reduce", "pig", "hive", "nosql",
          "mongodb", "cassandra", "mahout","google analytics|GA|big query",
          "adobe", "apis?", "nlp|natural language", "math?s|mathematics",
          "statistics|biostatistics", "physics", "computer science",
          "engineering", "economics", "finance"),
  stringsAsFactors = FALSE)

# count number of occurences of each word in the skills dataframe in
# the data science job descriptions
ds_occurs <- matrix(unlist(lapply(skills$regex,
                                function(x){str_count(ds_job_descripts,
                                                      paste0("\\b", x, "\\b"))})),
                  length(ds_job_descripts), length(skills$title))

# count number of occurences of each word in the skills dataframe in
# the data analyst job descriptions
da_occurs <- matrix(unlist(lapply(skills$regex,
                                function(x){str_count(da_job_descripts,
                                                      paste0("\\b", x, "\\b"))})),
                  length(da_job_descripts), length(skills$title))



그리하여 ds_occurs는 데이터 사이언티스트의 빈도수, da_occurs는 데이터 분석가의 빈도수를 측정하였습니다.
그래서 각 string에 해당되는 내용중에 math의 빈도수를 기록하여서 48개의 열에 그 빈도수를 기록하였습니다. 
하지만 한 string에서 math가 5번 나왔다고 math의 중요도가 높아지는 것은 아니므로, 
각 string에서 출현을 했다 혹은 안했다로만 확인하기 위해서 이진 행렬 (bineary matrix)로 바꿔야 합니다. 
그 작업은 아래와 같이 진행합니다. 


ds_occurs <- ifelse(ds_occurs>1, 1, ds_occurs)
da_occurs <- ifelse(da_occurs>1, 1, da_occurs)

그리하여 각 string별 skill 출현 빈도에 대한 그래프를 아래와 같이 그릴수 있습니다. 


plot_ly(rbind(data.frame(job = "Data Scientist",
                        skills = skills$title,
                        prop = round(
                          100*apply(ds_occurs, 2, sum)/nrow(ds_occurs), 2)),
              data.frame(job = "Data Analyst",
                        skills = skills$title,
                        prop = round(
                          100*apply(da_occurs, 2, sum)/nrow(da_occurs), 2))),
        x = ~skills, y = ~prop, color= ~job, type = 'bar') %>%
  layout(margin = list(b = 109),
        xaxis = list(title = "", tickfont = list(size = 12)),
        yaxis = list(title =
                        "<b>Appearance in Job Description (% Job Postings)</b>",
                      titlefont = list(size = 16)),
        title = "<b>Job Description Skills: Data Scientist v Data Analyst</b>",
        titlefont = list(size=17)) %>%
  layout(legend=list(font = list(size = 16))) %>%
  layout(autosize = F, width = 1200, height = 800)

\



그래프를 확인해보면 데이터 과학자와 데이터 분석가의  skill 에 대한 내용이 크게 다르다는 것을 알수 있습니다. . 파이썬과 R을 데이터 과학자들에게 가장 일반적으로 요구되는 skill로 나타나는 것이 흥미 롭습니다.
Excel은 데이터 분석가가 가장 많이 사용하는 기술이며 SQL을 밀접하게 따르고 있습니다. 사실, SQL은 두 가지 직종 모두에서 비교적 높은 빈도로 나타납니다.
 
따라서 데이터 과학 / 분석을 배우려는 경우 SQL을 먼저 배워보는 것도 좋은 선택이라고 할수 있을 것입니다. 

또한 위의 그래프를 보면 막대 그래프는 일반적으로 데이터 분석가 그룹에서 훨씬 작은 횟수로 나타납니다.
즉 우리가 정의한 48가지 skill set에 해당되는 내용이 데이터 분석가 그룹의 내용에는 상대적으로 적은 횟수로 나타났다는 것입니다. 이것은 아래와 같이 직업 설명별로 언급 된
다양한 skill의 가짓수를 누적 분포를 통해 그래프를 그려볼수 있습니다. 

ggplot(rbind(data.frame(type = "Data Scientist",
                        num_skills = apply(ds_occurs,1,sum)),
            data.frame(type = "Data Analyst",
                        num_skills = apply(da_occurs,1,sum))),
      aes(num_skills, colour = type)) + stat_ecdf(size = 1) +
  geom_text(size=8, aes(20, .3, label = "Data Analyst", color = "Data Analyst")) +
  geom_text(size=8, aes(20, .2, label = "Data Scientist", color= "Data Scientist")) +
  labs(title = "# Skills in Job Description: Data Analysts vs Data Scientists",
      x = "Number of Skills", y = "Cumulative Proportion") +
  theme(axis.title = element_text(size = 14,face = "bold"),
        plot.title = element_text(size = 16,face = "bold"), legend.position = "none",
        axis.text = element_text(size = 11))

아래 그래프를 확인하면 데이터 분석가는 5개 미만의 skill만 가지고 있어도 70%의 구인광고에 지원을 해볼수 있겠지만,
데이터 과학자는 5개의 skill로는 고작 15%의 구인광고에 지원을 해볼수 있게 됩니다. 즉 데이터 과학자에게 요구하는 수준이 상대적으로 데이터 분석가보다 많다는 것을 나타내는 그래프라고 할수 있습니다. 







+ Recent posts