"рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреЗ рдмрд╛рдЬрд╛рд░ рдкрд░ рд╢реЛрдз рдХрд░рдирд╛" рдПрдХ рдмрдбрд╝реА рдпрд╛ рдЫреЛрдЯреА рдХрдВрдкрдиреА рдХреЗ рдПрдХ рдмрд╣реБрдд рд╣реА рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдЧреНрд░рдгреА рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдХрд╛рд░реНрдп рдерд╛ред рдкрд╛рд░реНрд╕рд░ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдПрдЪрдПрдЪ рдХреЗ рд╕рд╛рде рджрд░реНрдЬрдиреЛрдВ рдиреМрдХрд░реА рд╡рд┐рд╡рд░рдгреЛрдВ рдХреЛ рдкрд╛рд░реНрд╕рд▓ рдХрд░рддрд╛ рд╣реИ, рдЙрдиреНрд╣реЗрдВ рдЕрдиреБрд░реЛрдз рдХрд┐рдП рдЧрдП рдХреМрд╢рд▓ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдмрд┐рдЦрд░рддрд╛ рд╣реИ рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рд╕реНрдкреНрд░реЗрдбрд╢реАрдЯ рдХреЙрд▓рдо рдореЗрдВ рдХрд╛рдЙрдВрдЯрд░ рдмрдврд╝рд╛рддрд╛ рд╣реИред
рдореИрдВрдиреЗ рдЗрд╕ рдХрд╛рд░реНрдп рдореЗрдВ рд╕реНрд╡рдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫрд╛ рдХреНрд╖реЗрддреНрд░ рджреЗрдЦрд╛ рдФрд░ рдХрдо рд░рдХреНрдд рдХреЗ рд╕рд╛рде рдЖрд╕рд╛рдиреА рд╕реЗ рдФрд░ рд╕рд░рд▓рддрд╛ рд╕реЗ рд╕рд╛рдордирд╛ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред
рдореБрдЭреЗ рдЗрд╕ рдЕрдзреНрдпрдпрди рдореЗрдВ рдЙрдард╛рдП рдЧрдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореБрджреНрджреЛрдВ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рдереА:
- рд╡реНрдпрд╛рдкрд╛рд░ рдФрд░ рд╕рд┐рд╕реНрдЯрдо рд╡рд┐рд╢реНрд▓реЗрд╖рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдФрд╕рдд рд╡реЗрддрди,
- рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдорд╛рдВрдЧ рд╡рд╛рд▓реЗ рдХреМрд╢рд▓ рдФрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдЧреБрдг,
- рдХреБрдЫ рдХреМрд╢рд▓ рдФрд░ рд╡реЗрддрди рдХреЗ рд╕реНрддрд░ рдХреЗ рдмреАрдЪ рдирд┐рд░реНрднрд░рддрд╛ (рдпрджрд┐ рдХреЛрдИ рд╣реЛ)ред
Spoiler: рдЖрд╕рд╛рди рдФрд░ рд╕рд░рд▓ рдХрд╛рдо рдирд╣реАрдВ рдХрд┐рдпрд╛ред
рдбреЗрдЯрд╛ рдХреА рддреИрдпрд╛рд░реА
рдпрджрд┐ рд╣рдо рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдбреЗрдЯрд╛ рдПрдХрддреНрд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рддрд░реНрдХрд╕рдВрдЧрдд рд╣реИ рдХрд┐ hh рд╕реАрдорд┐рдд рдирд╣реАрдВ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдХреЗ рд▓рд┐рдП рд╢реБрджреНрдзрддрд╛ рдХрд╛ рдкреНрд░рдпреЛрдЧ рдХрд░реЗрдВ рд╕рд╛рджрдЧреА, рд╣рдо рдЗрд╕ рд╕рдВрд╕рд╛рдзрди рд╕реЗ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред
рд╕рдВрдЧреНрд░рд╣
рдбреЗрдЯрд╛ рдПрдХрддреНрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо hh рдПрдкреАрдЖрдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдиреМрдХрд░реА рдЦреЛрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред
рдореИрдВ рд╕рд░рд▓ рдЯреЗрдХреНрд╕реНрдЯ рдХреНрд╡реЗрд░реА "рд╕рд┐рд╕реНрдЯрдо рдПрдирд╛рд▓рд┐рд╕реНрдЯ", "рдмрд┐рдЬрдиреЗрд╕ рдПрдирд╛рд▓рд┐рд╕реНрдЯ" рдФрд░ "рдкреНрд░реЛрдбрдХреНрдЯ рдУрдирд░" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЦреЛрдЬ рдХрд░реВрдВрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдирд┐рдпрдо рдХреЗ рддрд╣рдд рдЗрди рдкрджреЛрдВ рдХреА рдЧрддрд┐рд╡рд┐рдзрд┐рдпрд╛рдВ рдФрд░ рдХреНрд╖реЗрддреНрд░ рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ рдУрд╡рд░рд▓реИрдк рд╣реЛрддреЗ рд╣реИрдВред
рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, https://api.hh.ru/vacancies?text="systems+analyst"
рдлреЙрд░реНрдо рдХрд╛ рдЕрдиреБрд░реЛрдз рдмрдирд╛рдПрдВ рдФрд░ рдкреНрд░рд╛рдкреНрдд JSON рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░реЗрдВред
рдирдореВрдиреЗ рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдХреЗрд╡рд▓ рд░рд┐рдХреНрддрд┐ рд╣реЗрдбрд░ рдореЗрдВ search_field=name
рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рдХреНрд╡реЗрд░реА рдореЗрдВ рдЬреЛрдбрд╝рдХрд░ рдЦреЛрдЬ рдХрд░реЗрдВрдЧреЗред
рдпрд╣рд╛рдВ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдХреМрди рд╕реЗ рд░рд┐рдХреНрдд рдХреНрд╖реЗрддреНрд░ рд╡рд╛рдкрд╕ рдЖ рдЧрдП рд╣реИрдВред рдореИрдВрдиреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛ рдЪреБрдирд╛:
- рдиреМрдХрд░реА рдХрд╛ рд╢реАрд░реНрд╖рдХ
- рд╢рд╣рд░
- рдкреНрд░рдХрд╛рд╢рди рдХреА рддрд╛рд░реАрдЦ
- рд╡реЗрддрди - рдКрдкрд░реА рдФрд░ рдирд┐рдЪрд▓реЗ рд╕реАрдорд╛
- рд╡рд╣ рдореБрджреНрд░рд╛ рдЬрд┐рд╕рдореЗрдВ рд╡реЗрддрди рдХрд╛ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
- рд╕рдХрд▓ - рдЯреА / рдПрдл
- рдХрдВрдкрдиреА
- рдХрд░реНрддрд╡реНрдпреЛрдВ
- рдЙрдореНрдореАрджрд╡рд╛рд░ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХрддрд╛рдПрдВ
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рдЙрди рдХреМрд╢рд▓реЛрдВ рдХрд╛ рдФрд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдЬреЛ рдХреБрдВрдЬреА рдХреМрд╢рд▓ рдЕрдиреБрднрд╛рдЧ рдореЗрдВ рдЗрдВрдЧрд┐рдд рдХрд┐рдП рдЧрдП рд╣реИрдВ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрдиреБрднрд╛рдЧ рдХреЗрд╡рд▓ рдкреВрд░реНрдг рдиреМрдХрд░реА рд╡рд┐рд╡рд░рдг рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИред рдЗрд╕рд▓рд┐рдП, рдореИрдВ рд░рд┐рдХреНрдд рдкрджреЛрдВ рдХреЗ рд▓рд┐рдВрдХ рднреА рд░рдЦреВрдВрдЧрд╛, рддрд╛рдХрд┐ рдмрд╛рдж рдореЗрдВ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рд▓рд┐рдП рдХреМрд╢рд▓ рдХреА рдПрдХ рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХреЗред
рдХреЛрдб рджреЗрдЦреЗрдВ # :) library(jsonlite) library(curl) library(dplyr) library(ggplot2) library(RColorBrewer) library(plotly) hh.getjobs <- function(query, paid = FALSE) { # Makes a call to hh API and gets the list of vacancies based on the given search queries df <- data.frame( query = character() # , URL = character() # , id = numeric() # id , Name = character() # , City = character() , Published = character() , Currency = character() , From = numeric() # . , To = numeric() # . , Gross = character() , Company = character() , Responsibility = character() , Requerement = character() , stringsAsFactors = FALSE ) for (q in query) { for (pageNum in 0:99) { try( { data <- fromJSON(paste0("https://api.hh.ru/vacancies?search_field=name&text=\"" , q , "\"&search_field=name" , "&only_with_salary=", paid ,"&page=" , pageNum)) df <- rbind(df, data.frame( q, data$items$url, as.numeric(data$items$id), data$items$name, data$items$area$name, data$items$published_at, data$items$salary$currency, data$items$salary$from, data$items$salary$to, data$items$salary$gross, data$items$employer$name, data$items$snippet$responsibility, data$items$snippet$requirement, stringsAsFactors = FALSE)) }) print(paste0("Downloading page:", pageNum + 1, "; query = \"", q, "\"")) } } names <- c("query", "URL", "id", "Name", "City", "Published", "Currency", "From", "To", "Gross", "Company", "Responsibility", "Requirement") colnames(df) <- names return(df) }
hh.getjobs()
рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рдЗрдирдкреБрдЯ рд╕реЗ рд╣рдореЗрдВ рдФрд░ рдкрд░рд┐рд╢реЛрдзрди рдХреЗ рд▓рд┐рдП рд░реБрдЪрд┐ рдХреЗ рдЦреЛрдЬ рдкреНрд░рд╢реНрдиреЛрдВ рдХрд╛ рдПрдХ рд╡реЗрдХреНрдЯрд░ рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рд╣рдо рдХреЗрд╡рд▓ рдПрдХ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╡реЗрддрди рдпрд╛ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рд╕рднреА рдХреЗ рд╕рд╛рде рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рд╣рдо рджреВрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк рд▓реЗрддреЗ рд╣реИрдВ)ред рдПрдХ рдЦрд╛рд▓реА dafa рдлрд╝реНрд░реЗрдо рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ fromJSON()
рдкреИрдХреЗрдЬ рдХреЗ fromJSON()
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ jsonlite
, рдЬреЛ рдЗрдирдкреБрдЯ URL рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдПрдХ рд╕рдВрд░рдЪрд┐рдд рд╕реВрдЪреА рджреЗрддрд╛ рд╣реИред рдЕрдЧрд▓рд╛, рдЗрд╕ рд╕реВрдЪреА рдореЗрдВ рдиреЛрдбреНрд╕ рд╕реЗ, рд╣рдореЗрдВ рд╡рд╣ рдбреЗрдЯрд╛ рдорд┐рд▓рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рдбреЗрдЯрд╛ рдлрд╝реНрд░реЗрдо рдлрд╝реАрд▓реНрдб рдореЗрдВ рднрд░рддреЗ рд╣реИрдВред
рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ, рдбреЗрдЯрд╛ рдкреГрд╖реНрда рджреНрд╡рд╛рд░рд╛ рдкреГрд╖реНрда рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдкреГрд╖реНрда рдкрд░ 20 рддрддреНрд╡реЛрдВ рдХреЗ рд╕рд╛рдеред рдЕрдзрд┐рдХрддрдо 2,000 рдиреМрдХрд░реА рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдПред рд╣рдорд╛рд░реЗ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╛рдкреНрдд рд╕рднреА рдбреЗрдЯрд╛ df
рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЬреАрд╡рди рд╣реИрдХ 1: рдпрд╣ рдЗрд╕ рддрдереНрдп рдкрд░ рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдЕрдиреБрд░реЛрдз рдкрд░ 2,000 рд░рд┐рдХреНрддрд┐рдпрд╛рдВ рд╣реЛрдВрдЧреА, рдФрд░ рдХреБрдЫ рдмрд┐рдВрджреБрдУрдВ рдкрд░ рд╢реБрд░реВ рд╣реЛрдиреЗ рдкрд░ рд╣рдореЗрдВ рдЦрд╛рд▓реА рдкреГрд╖реНрда рдкреНрд░рд╛рдкреНрдд рд╣реЛрдВрдЧреЗред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрд░ рдХрд╕рдо рдЦрд╛рддрд╛ рд╣реИ рдФрд░ рд▓реВрдк рд╕реЗ рдмрд╛рд╣рд░ рдХреВрджрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдзреНрдпрд╛рди рд╕реЗ try()
рдореЗрдВ рдЖрдВрддрд░рд┐рдХ рд▓реВрдк рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рд▓рдкреЗрдЯрддреЗ рд╣реИрдВред
рдЬреАрд╡рди рд╣реИрдХ 2: рдпрд╣ рдЖрдВрддрд░рд┐рдХ рд▓реВрдк рдореЗрдВ рдХрдВрд╕реЛрд▓ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣ рд╕реНрдерд┐рддрд┐ рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдПрдХ рддреЗрдЬрд╝ рд╡реНрдпрд╡рд╕рд╛рдп рдирд╣реАрдВ рд╣реИред рдореИрдВрдиреЗ рдРрд╕рд╛ рдХрд┐рдпрд╛:
print(paste0("Downloading page:", pageNum + 1, "; query = \"", query, "\""))
рдбреЗрдЯрд╛ рднрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдХреЙрд▓рдо рдХрд╛ рдирд╛рдо рдмрджрд▓ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реЛ, рдФрд░ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдбреЗрдЯрд╛ рдлрд╝реНрд░реЗрдо рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПред
рдореИрдВ рдЗрд╕реЗ рдФрд░ рдЕрдиреНрдп рд╕рд╣рд╛рдпрдХ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдПрдХ рдЕрд▓рдЧ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реВрдВрдЧрд╛ред рдореБрдЦреНрдп рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдЕрд╡реНрдпрд╡рд╕реНрдерд┐рдд рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлрд╛рдЗрд▓ рдХрд░реЗрдВ, рдЬреЛ рдЕрдм рддрдХ рдРрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:
source("functions.R") # Step 1 - get data # 1.1 get vacancies (short info) jobdf <- hh.getjobs(query = c("business+analyst" , "systems+analyst" , "product+owner"), paid = FALSE)
рдЕрдм рд╣рдореЗрдВ рдкреВрд░реНрдг рдиреМрдХрд░реА рд╡рд┐рд╡рд░рдг рд╕реЗ experience
рдФрд░ key_skills
ред
hh.getxp
рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдбреЗрдЯрд╛ рдлрд╝реНрд░реЗрдо рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд╣реЗрдЬреЗ рдЧрдП рд▓рд┐рдВрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рддреЗ рд╣реИрдВ, рдФрд░ рдкреВрд░реНрдг рд╡рд┐рд╡рд░рдг рд╕реЗ рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХ рдХрд╛рд░реНрдп рдЕрдиреБрднрд╡ рдХрд╛ рдореВрд▓реНрдп рдорд┐рд▓рддрд╛ рд╣реИред рдкрд░рд┐рдгрд╛рдореА рдорд╛рди рдПрдХ рдирдП рдХреЙрд▓рдо рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдХреЛрдб рджреЗрдЦреЗрдВ hh.getxp <- function(df) { df$experience <- NA for (myURL in df$URL) { try( { data <- fromJSON(myURL) df[df$URL == myURL, "experience"] <- data$experience$name } ) print(paste0("Filling in ", which(df$URL == myURL, arr.ind = TRUE), "from ", nrow(df))) } return(df) }
рдирдП рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рд╡рд┐рд╡рд░рдг рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рднреЗрдЬрд╛ рдЬрд╛рддрд╛ functions.R
ред рдФрд░ рдореБрдЦреНрдп рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЕрдм рдЗрд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рддреА рд╣реИ:
# s.1.2 get experience (from full info) jobdf <- hh.getxp(jobdf) # 1.3 get skills (from full info) all.skills <- hh.getskills(jobdf$URL)
рдКрдкрд░ рдХреЗ рдЯреБрдХрдбрд╝реЗ рдореЗрдВ, рд╣рдо рдПрдХ рдирдпрд╛ рдбреЗрдЯрд╛ рдлреНрд░реЗрдо рднреА all.skills
рдлреЙрд░реНрдо рдХреА "рдЬреЙрдм рдЖрдИрдбреА - рд╕реНрдХрд┐рд▓":
рдХреЛрдб рджреЗрдЦреЗрдВ hh.getskills <- function(allurls) { analyst.skills <- data.frame( id = character(), # id skill = character() # ) for (myURL in allurls) { data <- fromJSON(myURL) if (length(data$key_skills) > 0) analyst.skills <- rbind(analyst.skills, cbind(data$id, data$key_skills)) print(paste0("Filling in " , which(allurls == myURL, arr.ind = TRUE) , " out of " , length(allurls))) } names(analyst.skills) <- c("id", "skill") analyst.skills$skill <- tolower(analyst.skills$skill) return(analyst.skills) }
preprocessing
рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рд╣рдо рдХрд┐рддрдирд╛ рдбреЗрдЯрд╛ рдПрдХрддреНрд░ рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣реЗ:
> length(unique(jobdf$id)) [1] 1478 > length(jobdf$id) [1] 1498
рд▓рдЧрднрдЧ рдбреЗрдврд╝ рд╣рдЬрд╛рд░ рдиреМрдХрд░рд┐рдпрд╛рдВ! рдпрд╣ рдЕрдЪреНрдЫрд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИред рдФрд░ рдЬрд╛рд╣рд┐рд░ рд╣реИ, рдХрдИ рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП - рджреЛ рдмрд╛рд░ рдЦреЛрдЬ рдкрд░рд┐рдгрд╛рдореЛрдВ рдореЗрдВ рдорд┐рд▓рд╛ред рдЗрд╕рд▓рд┐рдП, рдкрд╣рд▓рд╛ рдХрджрдо рдХреЗрд╡рд▓ рдЕрджреНрд╡рд┐рддреАрдп рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпреЛрдВ рдХреЛ рдЫреЛрдбрд╝рдирд╛ рд╣реИ: jobdf <- jobdf[unique(jobdf$id),]
ред
рд╢реНрд░рдо рдмрд╛рдЬрд╛рд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдХреЛрдВ рдХреЗ рд╡реЗрддрди рдХреА рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ
1) рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рд╡реЗрддрди рдкрд░ рд╕рднреА рдЙрдкрд▓рдмреНрдз рдбреЗрдЯрд╛ рдПрдХ рд╣реА рдореБрджреНрд░рд╛ рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ,
2) рдПрдХ рдЕрд▓рдЧ рдбреЗрдЯрд╛ рдлреНрд░реЗрдо рдореЗрдВ рдЙрди рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ рдЬрд┐рдирдХреЗ рд▓рд┐рдП рд╡реЗрддрди рдХрд╛ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрдХрдерд╛ рдХреЛ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдорд╛рдирддреЗ рд╣реИрдВред рдкрд╣рд▓реЗ, рдЖрдк рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдореБрджреНрд░рд╛рдПрдВ table(jobdf$Currency)
рдореЗрдВ рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛ рдореЗрдВ рдкрд╛рдИ рдЬрд╛рддреА рд╣реИрдВ table(jobdf$Currency)
ред рдореЗрд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд░реВрдмрд▓ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдбреЙрд▓рд░, рдпреВрд░реЛ, hryvnias, рдХрдЬрд╛рдЦ рдХрд╛ рдХрд╛рд░реНрдпрдХрд╛рд▓ рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЙрдЬрд╝реНрдмреЗрдХ рд░рдХрдо рджрд┐рдЦрд╛рдИ рджрд┐рдПред
рд╡реЗрддрди рдорд╛рдиреЛрдВ рдХреЛ рд░реВрдмрд▓ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╡рд░реНрддрдорд╛рди рд╡рд┐рдирд┐рдордп рджрд░ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рд╣реЛрдЧрд╛ред рд╣рдо рд╕реЗрдВрдЯреНрд░рд▓ рдмреИрдВрдХ рд╕реЗ рдкрддрд╛ рд▓рдЧрд╛рдПрдВрдЧреЗ:
рдХреЛрдб рджреЗрдЦреЗрдВ quotations.update <- function(currencies) { # Parses the most up-to-date qutations data provided by the Central Bank of Russia # and returns a table with currency rate against RUR doc <- XML::xmlParse("http://www.cbr.ru/scripts/XML_daily.asp") quotationsdf <- XML::xmlToDataFrame(doc, stringsAsFactors = FALSE) quotationsdf <- select(quotationsdf, -Name) quotationsdf$NumCode <- as.numeric(quotationsdf$NumCode) quotationsdf$Nominal <- as.numeric(quotationsdf$Nominal) quotationsdf$Value <- as.numeric(sub(",", ".", quotationsdf$Value)) quotationsdf$Value <- quotationsdf$Value / quotationsdf$Nominal quotationsdf <- quotationsdf %>% select(CharCode, Value) return(quotationsdf) }
рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдкрд╛рдареНрдпрдХреНрд░рдо рдЖрд░ рдореЗрдВ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдП рдЧрдП рд╣реИрдВ, рдЖрдкрдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рджрд╢рдорд▓рд╡ рднрд╛рдЧ рдХреЛ рдПрдХ рдбреЙрдЯ рджреНрд╡рд╛рд░рд╛ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ рдирд╛рдордорд╛рддреНрд░ рд╕реНрддрдВрдн рдкрд░ рдзреНрдпрд╛рди рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП: рдХрд╣реАрдВ рдпрд╣ 1, рдХрд╣реАрдВ 10 рдпрд╛ 100 рд╣реИред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдПрдХ рдкрд╛рдЙрдВрдб рд╕реНрдЯрд░реНрд▓рд┐рдВрдЧ рдХреА рд▓рд╛рдЧрдд ~ 85 рд░реВрдмрд▓ рд╣реИ, рдФрд░ рдХрд╣рддреЗ рд╣реИрдВ, рдПрдХ рд╕реМ рдЕрд░реНрдореЗрдирд┐рдпрд╛рдИ рдбреНрд░рдо рдХреЗ рд▓рд┐рдП рдЖрдк ~ 13 рд░реВрдмрд▓ рдЦрд░реАрдж рд╕рдХрддреЗ рд╣реИрдВред рдЖрдЧреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рд░реВрдмрд▓ рдХреЗ рд╕рд╛рдкреЗрдХреНрд╖ 1 рдирд╛рдордорд╛рддреНрд░ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдХрдо рдХрд░ рджрд┐рдпрд╛ред
рдЕрдм рдЖрдк рдЕрдиреБрд╡рд╛рдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдорд╛рд░реА рд▓рд┐рдкрд┐ рдпрд╣ convert.currency()
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред рдЗрд╕рдореЗрдВ рдореМрдЬреВрджрд╛ рд╡рд┐рдирд┐рдордп рджрд░ quotations
рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рд▓реА рдЧрдИ рд╣реИ, рдЬрд╣рд╛рдВ рд╣рдордиреЗ рд╕реЗрдВрдЯреНрд░рд▓ рдмреИрдВрдХ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЧрдП рдПрдХреНрд╕рдПрдордПрд▓ рд╕реЗ рдбреЗрдЯрд╛ рдмрдЪрд╛рдпрд╛ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрдирдкреБрдЯ рдлрд╝рдВрдХреНрд╢рди рд░реВрдкрд╛рдВрддрд░рдг рдХреЗ рд▓рд┐рдП рд▓рдХреНрд╖реНрдп рдореБрджреНрд░рд╛ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЖрд░рдпреВрдЖрд░) рдФрд░ рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рд╡реЗрддрди рдХрд╛рдВрдЯреЗ рдХреЗ рдореВрд▓реНрдп рдЬрд┐рд╕рдореЗрдВ рдПрдХрд▓ рдореБрджреНрд░рд╛ рдХрд╛ рдиреЗрддреГрддреНрд╡ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдлрд╝рдВрдХреНрд╢рди рдЕрджреНрдпрддрди рд╡реЗрддрди рдЕрдВрдХреЛрдВ (рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдореБрджреНрд░рд╛ рдХреЙрд▓рдо рдХреЗ рдмрд┐рдирд╛, рдЕрдирд╛рд╡рд╢реНрдпрдХ рдХреЗ рд░реВрдк рдореЗрдВ) рдХреЗ рд╕рд╛рде рдПрдХ рддрд╛рд▓рд┐рдХрд╛ рджреЗрддрд╛ рд╣реИред
рдореБрдЭреЗ рдмреЗрд▓рд╛рд░реВрд╕реА рд░реВрдмрд▓ рдХреЗ рд╕рд╛рде рдЯрд┐рдВрдХрд░ рдХрд░рдирд╛ рдкрдбрд╝рд╛: рдХрдИ рджреГрд╖реНрдЯрд┐рдХреЛрдгреЛрдВ рдореЗрдВ рдмрд╣реБрдд рд╣реА рдЕрдЬреАрдм рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВрдиреЗ рдПрдХ рдЫреЛрдЯрд╛ рд╢реЛрдз рдХрд┐рдпрд╛ рдФрд░ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ 2016 рд╕реЗ рдмреЗрд▓рд╛рд░реВрд╕ рдореЗрдВ рдПрдХ рдирдИ рдореБрджреНрд░рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рди рдХреЗрд╡рд▓ рд╡рд┐рдирд┐рдордп рджрд░ рдореЗрдВ рднрд┐рдиреНрди рд╣реЛрддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд░реВрдк рдореЗрдВ (рдЕрдм BYR рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ BYN) ред Hh рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛рдУрдВ рдореЗрдВ , рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдирд╛рдо BYR рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрднреА рднреА рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЗрдВрдЯреНрд░рд▓ рдмреИрдВрдХ рдХреЗ XML рдХреЛ рдХреБрдЫ рднреА рдкрддрд╛ рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ convert.currency()
I рд╕рдмрд╕реЗ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рддрд░реАрдХреЗ рд╕реЗ рдирд╣реАрдВ рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВ рд╕рдВрдХреНрд╖реЗрдк рдХреЛ рд╡рд░реНрддрдорд╛рди рдХреЗ рд╕рд╛рде рдмрджрд▓ рджреЗрддрд╛ рд╣реВрдВ, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣реА рд╕реАрдзреЗ рд░реВрдкрд╛рдВрддрд░рдг рдкрд░ рдЬрд╛рддрд╛ рд╣реВрдВред
рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
рдХреЛрдб рджреЗрдЦреЗрдВ convert.currency <- function(targetCurrency = "RUR", df, quotationsdf) { cond <- (!is.na(df$Currency) & df$Currency == "BYR") df[cond, "Currency"] <- "BYN" currencies <- unique(na.omit(df$Currency[df$Currency != targetCurrency])) # ( ) if (!is.null(df$From)) { for (currency in currencies) { condition <- (!is.na(df$From) & df$Currency == currency) try( df$From[condition] <- df$From[condition] * quotationsdf$Value[quotationsdf$CharCode == currency] ) } } # ( ) if (!is.null(df$To)) { for (currency in currencies) { condition <- !is.na(df$To) & df$Currency == currency try( df$To[condition] <- df$To[condition] * quotationsdf$Value[quotationsdf$CharCode == currency] ) } } return(df %>% select(-Currency)) }
рдЖрдк рдпрд╣ рднреА рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╡реЗрддрди рдХреЗ рдХреБрдЫ рдбреЗрдЯрд╛ рдХреЛ рд╕рдХрд▓ рдореВрд▓реНрдпреЛрдВ рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЕрд░реНрдерд╛рдд, рдХрд░реНрдордЪрд╛рд░реА рдХреЛ рд╣рд╛рде рдкрд░ рдереЛрдбрд╝рд╛ рдХрдо рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛ред рд░реВрд╕реА рд╕рдВрдШ рдХреЗ рдирд┐рд╡рд╛рд╕рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╢реБрджреНрдз рд╡реЗрддрди рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрди рдЖрдВрдХрдбрд╝реЛрдВ рд╕реЗ 13% рдХрдЯреМрддреА рдХреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдП (рдЧреИрд░-рдирд┐рд╡рд╛рд╕рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП 30% рдХрдЯреМрддреА рдХреА рдЧрдИ рд╣реИ)ред
рдХреЛрдб рджреЗрдЦреЗрдВ gross.to.net <- function(df, resident = TRUE) { if (resident == TRUE) coef <- 0.87 else coef <- 0.7 if (!is.null(df$Gross)) { if (!is.null(df$From)) # ( ) { index <- na.omit(as.numeric(rownames(df[!is.na(df$From) & df$Gross == TRUE,]))) df$From[index] <- df$From[index] * coef } if (!is.null(df$To)) # ( ) { index <- na.omit(as.numeric(rownames(df[!is.na(df$To) & df$Gross == TRUE,]))) df$To[index] <- df$To[index] * coef } df <- df %>% select(-Gross) } return(df) }
рдмреЗрд╢рдХ, рдореИрдВ рдРрд╕рд╛ рдирд╣реАрдВ рдХрд░реВрдВрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рд╡рд┐рднрд┐рдиреНрди рджреЗрд╢реЛрдВ рдореЗрдВ рдХрд░реЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИ, рдФрд░ рди рдХреЗрд╡рд▓ рд░реВрд╕ рдореЗрдВ, рдпрд╛ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдореЗрдВ рджреЗрд╢ рджреНрд╡рд╛рд░рд╛ рдлрд╝рд┐рд▓реНрдЯрд░ рдЬреЛрдбрд╝реЗрдВред
рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╕реЗ рдкрд╣рд▓реЗ рдЕрдВрддрд┐рдо рдЪрд░рдг рддреАрди рд╢реНрд░реЗрдгрд┐рдпреЛрдВ: рдЬреВрди, рдордзреНрдп рдФрд░ рд╡рд░рд┐рд╖реНрда рдореЗрдВ рдорд┐рд▓реА рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдирд╛ рд╣реИ, рдФрд░ рдкреНрд░рд╛рдкреНрдд рдкрджреЛрдВ рдХреЛ рдПрдХ рдирдП рдХреЙрд▓рдо рдореЗрдВ рд▓рд┐рдЦрдирд╛ рд╣реИред рд╡рд░рд┐рд╖реНрда рдкрджреЛрдВ рдореЗрдВ рд╡реЗ рдирд╛рдо рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗ рдЬрд┐рдирдореЗрдВ "рд╡рд░рд┐рд╖реНрда" рдФрд░ рдЗрд╕рдХреЗ рдкрд░реНрдпрд╛рдпрд╡рд╛рдЪреА рд╢рдмреНрдж рдореМрдЬреВрдж рд╣реИрдВред рдЗрд╕реА рддрд░рд╣, рд╣рдо рдХреАрд╡рд░реНрдб "рдЬреВрдирд┐рдпрд░" рдФрд░ рд╕рдорд╛рдирд╛рд░реНрдердХ рд╢рдмреНрдж рдХреЗ рд▓рд┐рдП рд╢реБрд░реБрдЖрддреА рд╕реНрдерд┐рддрд┐ рдкрд╛рдПрдВрдЧреЗ, рдФрд░ рдЬрд┐рди рдкрд╣реЗрд▓рд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рд╣рдо рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЙрдирдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:
get.positions <- function(df) { df$lvl <- NA df[grep(pattern = "lead|senior|||", x = df$Name, ignore.case = TRUE), "lvl"] <- "senior" df[grep(pattern = "junior|||", x = df$Name, ignore.case = TRUE), "lvl"] <- "junior" df[is.na(df$lvl), "lvl"] <- "middle" return(df) }
рдореБрдЦреНрдп рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдореЗрдВ рдбреЗрдЯрд╛ рддреИрдпрд╛рд░реА рдмреНрд▓реЙрдХ рдЬреЛрдбрд╝реЗрдВред
рдЬреЛрдбрд╝рд╛ # Step 2 - prepare data # 2.1. Convert all currencies to target currency # 2.1.1 get up-to-date currency rates quotations <- quotations.update() # 2.1.2 convert to RUR jobdf <- convert.currency(df = jobdf, quotationsdf = quotations) # 2.2 convert Gross to Net # jobdf <- gross.to.net(df = jobdf) # 2.3 define segments jobdf <- get.positions(jobdf)
рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг
рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдореИрдВ рдкреНрд░рд╛рдкреНрдд рдЖрдВрдХрдбрд╝реЛрдВ рдХреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкрд╣рд▓реБрдУрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рдЬрд╛ рд░рд╣рд╛ рд╣реВрдВ:
- рдФрд╕рдд рд╡реЗрддрди рдмреАрдП / рдПрд╕рдП,
- рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдорд╛рдВрдЧ рд╡рд╛рд▓реЗ рдХреМрд╢рд▓ рдФрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдЧреБрдг,
- рдХреБрдЫ рдХреМрд╢рд▓ рдФрд░ рд╡реЗрддрди рдХреЗ рд╕реНрддрд░ рдХреЗ рдмреАрдЪ рдирд┐рд░реНрднрд░рддрд╛ (рдпрджрд┐ рдХреЛрдИ рд╣реЛ)ред
рдФрд╕рдд рдмреАрдП / рдПрд╕рдП рдЖрдп
рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдирд┐рдХрд▓рд╛, рдХрдВрдкрдирд┐рдпрд╛рдВ рдКрдкрд░реА рдпрд╛ рдирд┐рдореНрди рд╡реЗрддрди рд╕реАрдорд╛ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдирд┐рдЪреНрдЫреБрдХ рд╣реИрдВред
рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛ рдлрд╝реНрд░реЗрдо jobdf
рдпреЗ рдорд╛рди рдХреНрд░рдорд╢рдГ To рдФрд░ From рдХреЙрд▓рдо рдореЗрдВ рд╣реИрдВред рдореИрдВ рдФрд╕рдд рдЦреЛрдЬрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдПрдХ рдирдП рд╡реЗрддрди рдХреЙрд▓рдо рдореЗрдВ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред
рдЙрди рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП рдЬрд╣рд╛рдВ рд╡реЗрддрди рдкреВрд░реНрдг рд░реВрдк рд╕реЗ рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдпрд╣ рдЖрд╕рд╛рдиреА рд╕реЗ mean()
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЕрдиреНрдп рд╕рднреА рд░рд┐рдХреЙрд░реНрдбреЛрдВ рдХреЛ рдлрд╝рд┐рд▓реНрдЯрд░ рдХрд░ рд░рд╣рд╛ рд╣реИ рдЬрд╣рд╛рдВ рдкреНрд▓рдЧ рдкрд░ рдбреЗрдЯрд╛ рдкреВрд░реЗ рдпрд╛ рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдЧрд╛рдпрдм рд╣реИред рд▓реЗрдХрд┐рди рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, 10% рд╕реЗ рдХрдо рд╣рдорд╛рд░реЗ рдореВрд▓ рдирдореВрдиреЗ рд╕реЗ рдмрдиреЗ рд░рд╣реЗрдВрдЧреЗ, рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЫреЛрдЯрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдореИрдВ рдЧреБрдгрд╛рдВрдХ рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реВрдВ Podgoniana , рдЬреЛ рдЖрдкрдХреЛ рдмрддрд╛рддрд╛ рд╣реИ рдХрд┐ рдкреНрд░рддрд┐ рд░рд┐рдХреНрдд рд╕реНрдерд╛рди рдЬрд╣рд╛рдВ рдФрд╕рдд рд╕реЗ рдкреВрд░реНрдг рдХрд╛рдВрдЯреЗ рдХрд╛ рд╕рдВрдХреЗрдд рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдореЗрдВ рдФрд╕рдд рд╕реЗ рдХрд┐рддрдирд╛ рдЯреВ рдФрд░ рд╡реИрд▓реНрдпреВ рднрд┐рдиреНрди рд╣реИ, рдФрд░ рдЗрд╕рдХреА рдорджрдж рд╕реЗ рдореИрдВ рдЙрди рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд▓рд╛рдкрддрд╛ рдбреЗрдЯрд╛ рдХреЛ рднрд░рддрд╛ рд╣реВрдВ рдЬрд╣рд╛рдВ рдХреЗрд╡рд▓ рдПрдХ рдорд╛рди рдЧрд╛рдпрдм рд╣реИред
рдХреЛрдб рджреЗрдЦреЗрдВ select.paid <- function(df, suggest = TRUE) { # Returns a data frame with average salaries between To and From # optionally, can suggest To or From value in case only one is specified if (suggest == TRUE) { df <- df %>% filter(!is.na(From) | !is.na(To)) magic.coefficient <- # shows the average difference between max and min salary round(mean(df$To/df$From, na.rm = TRUE), 1) df[is.na(df$To),]$To <- df[is.na(df$To),]$From * magic.coefficient df[is.na(df$From),]$From <- df[is.na(df$From),]$To / magic.coefficient } else { df <- na.omit(df) } df$salary <- rowMeans(x = df %>% select(From, To)) df$salary <- ceiling(df$salary / 10000) * 10000 return(df %>% select(-From, -To)) }
рдпрд╣ рдПрдХ "рд╕реЙрдлреНрдЯ" рдбреЗрдЯрд╛ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рд╣реИ, рдЬреЛ suggest = TRUE
рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде select.paid()
рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ, рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╕рдордп suggest = FALSE
рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдмрд╕ рдЙрди рд╕рднреА рд▓рд╛рдЗрдиреЛрдВ рдХреЛ рдХрд╛рдЯ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рд╡реЗрддрди рдбреЗрдЯрд╛ рдХрдо рд╕реЗ рдХрдо рдЖрдВрд╢рд┐рдХ рд░реВрдк рд╕реЗ рдЕрдиреБрдкрд╕реНрдерд┐рдд рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдирд░рдо рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдФрд░ рдПрдХ рдЬрд╛рджреВ рдЧреБрдгрд╛рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдореИрдВ рдирдореВрдиреЗ рдореЗрдВ рдореВрд▓ рдбреЗрдЯрд╛ рдХреЗ рд▓рдЧрднрдЧ рдПрдХ рдЪреМрдерд╛рдИ рдХреЛ рдмрдЪрд╛рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ред
рд╣рдо рджреГрд╢реНрдп рднрд╛рдЧ рдореЗрдВ рдЬрд╛рддреЗ рд╣реИрдВ:

рдЗрд╕ рдЧреНрд░рд╛рдл рдкрд░ рдЖрдк рджреЛ рд░рд╛рдЬрдзрд╛рдирд┐рдпреЛрдВ рдФрд░ рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рдмреАрдП / рдПрд╕рдП рд╡реЗрддрди рдХреЗ рд╡рд┐рддрд░рдг рдШрдирддреНрд╡ рдХрд╛ рдиреЗрддреНрд░рд╣реАрди рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рд╣рдо рдЕрдиреБрд░реЛрдз рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рддреБрд▓рдирд╛ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд░рд╛рдЬрдзрд╛рдирд┐рдпреЛрдВ рдореЗрдВ рдордзреНрдпрдо рдФрд░ рд╡рд░рд┐рд╖реНрда рдкреБрд░реБрд╖реЛрдВ рдХреЛ рдХрд┐рддрдирд╛ рдорд┐рд▓рддрд╛ рд╣реИ?

рдкреНрд░рд╛рдкреНрдд рдЧреНрд░рд╛рдл рд╕реЗ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рдорд╛рд╕реНрдХреЛ рдФрд░ рд╕реЗрдВрдЯ рдкреАрдЯрд░реНрд╕рдмрд░реНрдЧ рдореЗрдВ рдордзреНрдпрдо рдФрд░ рд╡рд░рд┐рд╖реНрда рдкреБрд░реБрд╖реЛрдВ рдХреЗ рдмреАрдЪ рд╡реЗрддрди рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдЕрдВрддрд░ рдмрд╣реБрдд рдЕрд▓рдЧ рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╕реЗрдВрдЯ рдкреАрдЯрд░реНрд╕рдмрд░реНрдЧ рдореЗрдВ, рдорд┐рдбрд▓реНрд╕ рдХреЛ рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, 70 tr рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ, рдЬрдмрдХрд┐ рдорд╛рд╕реНрдХреЛ рдореЗрдВ рдШрдирддреНрд╡ рд╢рд┐рдЦрд░ ~ 120 tr рдкрд░ рдкрдбрд╝рддрд╛ рд╣реИ, рдФрд░ рдорд╛рд╕реНрдХреЛ рдФрд░ рд╕реЗрдВрдЯ рдкреАрдЯрд░реНрд╕рдмрд░реНрдЧ рдореЗрдВ рд╡рд░рд┐рд╖реНрда рд╕реНрддрд░ рдХреЗ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮреЛрдВ рдХреА рдЖрдп рдореЗрдВ рдЕрдВрддрд░ред 60 рд╣рдЬрд╛рд░ рдХреА рдФрд╕рдд рд╕реЗ рднрд┐рдиреНрди рд╣реЛрддрд╛ рд╣реИред
рд╣рдо рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реНрдерд┐рддрд┐ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдХреЛрдВ рдХреЗ рдорд╛рд╕реНрдХреЛ рд╡реЗрддрди рдкрд░ рднреА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ:

рдпрд╣ рдирд┐рд╖реНрдХрд░реНрд╖ рдирд┐рдХрд╛рд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдореЙрд╕реНрдХреЛ рдореЗрдВ рдЖрдЬ рдкреНрд░рд╡реЗрд╢ рд╕реНрддрд░ рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдХреЛрдВ рдХреА рдмрд╣реБрдд рдЕрдзрд┐рдХ рдорд╛рдВрдЧ рд╣реИ, рдФрд░ рдмреА) рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ, рдРрд╕реЗ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮреЛрдВ рдХреЗ рд▓рд┐рдП рдКрдкрд░реА рд╡реЗрддрди рд╕реАрдорд╛ рдорд┐рдбрд┐рд▓ рдФрд░ рд╕реАрдирд┐рдпрд░реНрд╕ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╕реАрдорд┐рдд рд╣реИред
рдПрдХ рдФрд░ рдЕрд╡рд▓реЛрдХрди: рдордзреНрдпрдо рдФрд░ рдЙрдЪреНрдЪ рд╕реНрддрд░ рдХреЗ рдореЙрд╕реНрдХреЛ рд╡рд┐рд╢реЗрд╖рдЬреНрдЮреЛрдВ рдХреЗ рдФрд╕рдд рдПрд╕рдПрди рдореЗрдВ рдПрдХ рдмрдбрд╝рд╛ рдЪреМрд░рд╛рд╣рд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИред рдпрд╣ рд╕рдВрдХреЗрдд рджреЗ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЗрди рджреЛ рдЪрд░рдгреЛрдВ рдХреЗ рдмреАрдЪ рдмрд╛рдЬрд╛рд░ рдореЗрдВ рдзреБрдВрдзрд▓реА рд╕реАрдорд╛ рд╣реИред
рдХрдЯреМрддреА рдХреЗ рддрд╣рдд рдЪрд╛рд░реНрдЯ рдХреЗ рд▓рд┐рдП рдкреВрд░реНрдг рдХреЛрдбред
рдирдЬрд╝рд░ # Step 3 - analyze salaries # 3.1 get paid jobs (with salaries specified) jobs.paid <- select.paid(jobdf) # 3.2 plot salaries density by region ggplotly(ggplot(jobs.paid, aes(salary, fill = region, colour = region)) + geom_density(alpha=.3) + scale_fill_discrete(guide = guide_legend(reverse=FALSE)) + scale_x_continuous(labels = function(x) format(x, scientific = FALSE), name = ", .", breaks = round(seq(min(jobs.paid$salary), max(jobs.paid$salary), by = 30000),1)) + scale_y_continuous(name = " ") + theme(axis.text.x = element_text(size=9), axis.title = element_text(size=10))) # 3.3 compare salaries for middle / senior in capitals ggplot(jobs.paid %>% filter(region %in% c("", "-"), lvl %in% c("senior", "middle")), aes(salary, fill = region, colour = region)) + facet_grid(lvl ~ .) + geom_density(alpha = .3) + scale_x_continuous(labels = function(x) format(x, scientific = FALSE), name = ", .", breaks = round(seq(min(jobs.paid$salary), max(jobs.paid$salary), by = 30000),1)) + scale_y_continuous(name = " ") + scale_fill_discrete(name = "") + scale_color_discrete(name = "") + guides(fill=guide_legend( keywidth=0.1, keyheight=0.1, default.unit="inch") ) + theme(legend.spacing = unit(1,"inch"), axis.title = element_text(size=10)) # 3.4 plot salaries in Moscow by position ggplotly(ggplot(jobs.paid %>% filter(region == ""), aes(salary, fill = lvl, color = lvl)) + geom_density(alpha=.4) + scale_fill_brewer(palette = "Set2") + scale_color_brewer(palette = "Set2") + theme_light() + scale_y_continuous(name = " ") + scale_x_continuous(labels = function(x) format(x, scientific = FALSE), name = ", .", breaks = round(seq(min(jobs.paid$salary), max(jobs.paid$salary), by = 30000),1)) + theme(axis.text.x = element_text(size=9), axis.title = element_text(size=10)))
рдкреНрд░рдореБрдЦ рдХреМрд╢рд▓ рд╡рд┐рд╢реНрд▓реЗрд╖рдг
рд╣рдо рдмреАрдП / рдПрд╕рдП рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдорд╛рдВрдЧ рд╡рд╛рд▓реЗ рдХреМрд╢рд▓ рдХреА рдкрд╣рдЪрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП - рдЕрдзреНрдпрдпрди рдХреЗ рдкреНрд░рдореБрдЦ рд▓рдХреНрд╖реНрдп рдкрд░ рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЙрд╕ рдбреЗрдЯрд╛ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВрдЧреЗ рдЬреЛ рд░рд┐рдХреНрддрд┐ рдХреЗ рд╡рд┐рд╢реЗрд╖ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ - рдкреНрд░рдореБрдЦ рдХреМрд╢рд▓ред
рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рдХреМрд╢рд▓
рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдПрдХ рдЕрд▓рдЧ рдбреЗрдЯрд╛ рдлреНрд░реЗрдо all.skills
, рдЬрд╣рд╛рдВ рд╣рдо рдЬреЛрдбрд╝реЗ "рдиреМрдХрд░реА рдЖрдИрдбреА - рдХреМрд╢рд▓" рджрд░реНрдЬ рдХреА рдЧрдИред table()
рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рд╕рдмрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рдХреМрд╢рд▓ рдЦреЛрдЬрдирд╛ рдЖрд╕рд╛рди рд╣реИ:
tmp <- as.data.frame(table(all.skills$skill), col.names = c("Skill", "Freq")) htmlTable::htmlTable(x = head(tmp[order(tmp$Freq, na.last = TRUE, decreasing = TRUE),]), rnames = FALSE, header = c("Skill", "Freq"), align = 'l', css.cell = "padding-left: .5em; padding-right: 2em;")
рдЖрдкрдХреЛ рдирд┐рдореНрди рдЬреИрд╕рд╛ рдХреБрдЫ рдорд┐рд▓рддрд╛ рд╣реИ:

рдпрд╣рд╛рдВ рдлреНрд░реАрдХ "рдХреА_рд╕реНрдХрд┐рд▓реНрд╕" рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдХреМрд╢рд▓ рдХреЙрд▓рдо рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдХреМрд╢рд▓ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
"рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдм рдирд╣реАрдВ рд╣реИ!" (рд╕реА) рдпрд╣ рдХрд╛рдлреА рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рд╕рдорд╛рди рдХреМрд╢рд▓ рдЖрд╕рд╛рдиреА рд╕реЗ рдкрд░реНрдпрд╛рдп рд╢рдмреНрджреЛрдВ рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рд░рд┐рдХреНрддрд┐рдпреЛрдВ рдореЗрдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдореИрдВрдиреЗ рдХреМрд╢рд▓ рдХреЗ рдирд╛рдо рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдирд╛рд░реНрдердХ рд╢рдмреНрдж рдХрд╛ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╢рдмреНрджрдХреЛрд╢ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ред
рд╢рдмреНрджрдХреЛрд╢ рд╢реНрд░реЗрдгреА рдХреЙрд▓рдо рдХреЗ рд╕рд╛рде рдПрдХ рд╕реАрдПрд╕рд╡реА рдлрд╝рд╛рдЗрд▓ рд╣реИ - рдирд┐рдореНрди рдореЗрдВ рд╕реЗ рдПрдХ: рдЧрддрд┐рд╡рд┐рдзрд┐рдпрд╛рдБ, рдЙрдкрдХрд░рдг, рдЬреНрдЮрд╛рди, рдорд╛рдирдХ рдФрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд; рдХреМрд╢рд▓ - рдХреМрд╢рд▓ рдХрд╛ рдореБрдЦреНрдп рдирд╛рдо, рдЬрд┐рд╕реЗ рдореИрдВ рд╕рднреА рд╕рдорд╛рдирд╛рд░реНрдердХ рд╢рдмреНрдж рдХреЗ рдмрдЬрд╛рдп рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛; syn1, syn2, ... syn13 - рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХреМрд╢рд▓ рдХреЗ рд▓рд┐рдП рд╕рдВрднрд╡ рдмрджрд▓рд╛рд╡ред рдХреБрдЫ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдореЗрдВ рд╕рдорд╛рдирд╛рд░реНрдердХ рд╢рдмреНрдж рдХреЗ рдЦрд╛рд▓реА рдХреЙрд▓рдо рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред
category;skill;syn1;syn2;syn3;syn4;syn5;syn6;syn7;syn8;syn9;syn10;syn11;syn12;syn13 tools;axure;;;;;;;;;;;;; tools;lucidchart;;;;;;;;;;;;; standards;archimate;;;;;;;;;;;;; standards;uml;activity diagram;use case diagram;ucd;class diagram;;;;;;;;; personal;teamwork;team player; ;;;;;;;;;;; activities;wireframing;mockup;mock-up;;-;wireframe;;ui;ux/;/ux;;;;
рдкрд╣рд▓реЗ, рд╢рдмреНрджрдХреЛрд╢ рдЖрдпрд╛рдд рдХрд░реЗрдВ, рдФрд░ рдлрд┐рд░ рдореМрдЬреВрджрд╛ рд╕рдорддреБрд▓реНрдпрддрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдХреМрд╢рд▓ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╡рд┐рддрд░рд┐рдд рдХрд░реЗрдВ:
# Analyze skills # 4.1 import dictionary dict <- read.csv(file = "competencies.csv", header = TRUE, stringsAsFactors = FALSE, sep = ";", na.strings = "", encoding = "UTF-8") # 4.2 match skills with dictionary all.skills <- categorize.skills(all.skills, dict)
рдХрдЯ рдХреЗ рддрд╣рдд, рдЖрдк categorize.skills()
ред categorize.skills()
рдлрд╝рдВрдХреНрд╢рди рдХреЗ рднрд░рд╛рдИ рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред
рдмрд╣реБрдд рд╣рд┐рдореНрдордд! categorize.skills <- function(analyst_skills, dictionary) { analyst_skills$skill.group <- NA analyst_skills$category <- NA for (myskill in dictionary$skill) { category <- dictionary[dictionary$skill == myskill, "category"] mypattern <- paste0(na.omit(t(dictionary %>% filter(skill == myskill) %>% select(starts_with("syn")))), collapse = "|") if (nchar(mypattern) > 1) mypattern <- paste0(c(myskill, mypattern), collapse = "|") else mypattern <- myskill try( { analyst_skills[grep(x = analyst_skills$skill, pattern = mypattern),"skill.group"] <- myskill analyst_skills[grep(x = analyst_skills$skill, pattern = mypattern),"category"] <- category } ) } return(analyst_skills) }
рдореИрдВ рдореВрд▓ рдХреМрд╢рд▓ рдбреЗрдЯрд╛ рдлрд╝реНрд░реЗрдо рдореЗрдВ рд╢реНрд░реЗрдгреА рдФрд░ рдХреМрд╢рд▓ рдХреЙрд▓рдо рдЬреЛрдбрд╝рддрд╛ рд╣реВрдВред рд╕рдореВрд╣ - рдХреНрд░рдорд╢рдГ рд╢реНрд░реЗрдгреА рдФрд░ рдХреМрд╢рд▓ рдХреЗ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдирд╛рдо рдХреЗ рд▓рд┐рдПред рдлрд┐рд░ рдореИрдВ рдЖрдпрд╛рддрд┐рдд рд╢рдмреНрджрдХреЛрд╢ рд╕реЗ рдЧреБрдЬрд░рддрд╛ рд╣реВрдВ рдФрд░ рд╕рдорд╛рдирд╛рд░реНрдердХ рд╢рдмреНрдж рдХреА рдкреНрд░рддреНрдпреЗрдХ рдкрдВрдХреНрддрд┐ рд╕реЗ grep()
рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдкреИрдЯрд░реНрди grep()
рд╣реВрдВред рдкрдВрдХреНрддрд┐ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЧреИрд░-рд░рд┐рдХреНрдд рд╕реНрддрдВрдн рдорд╛рди рдЬреЛрдбрд╝рдХрд░, рдореИрдВ рдЙрдиреНрд╣реЗрдВ "рдпрд╛" рд╕реНрдерд┐рддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреИрд╢ рдХреЗ рд╕рд╛рде рдЕрд▓рдЧ рдХрд░рддрд╛ рд╣реВрдВред рдЗрд╕рд▓рд┐рдП, рд╕реНрд░реЛрдд рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рд╕рднреА рдХреМрд╢рд▓реЛрдВ рдХреЗ рд▓рд┐рдП, рдЬрд┐рд╕рдореЗрдВ uml|activity diagram|use case diagram|ucd|class diagram
рд╢рд╛рдорд┐рд▓ рд╣реИ uml|activity diagram|use case diagram|ucd|class diagram
, рдореИрдВ рдХреМрд╢рд▓ рдореЗрдВ "uml" рдорд╛рди рд▓рд┐рдЦреВрдВрдЧрд╛ред рд╕рдореВрд╣ рдХреЙрд▓рдоред рдФрд░ рдЗрд╕рд▓рд┐рдП рдпрд╣ рд╕рднреА рдХреЗ рд╕рд╛рде рд╣реЛрдЧрд╛! .. рдореВрд▓ рдбреЗрдЯрд╛ рдлреНрд░реЗрдо рд╕реЗ рдХреМрд╢рд▓ред
рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рдХреМрд╢рд▓ рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдлрд┐рд░ рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░рдХреЗ, рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдмрд▓реЛрдВ рдХрд╛ рд╕рдВрд░реЗрдЦрдг рдХреБрдЫ рд╣рдж рддрдХ рдмрджрд▓ рдЧрдпрд╛ рд╣реИ:

рддреАрди рдиреЗрддрд╛рдУрдВ рдХреЗ рдкрд╛рд╕ рдЕрдм рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкреНрд░рдмрдВрдзрди, рд╡реНрдпрд╡рд╕рд╛рдп рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдФрд░ рдкреНрд░рд▓реЗрдЦрди рд╣реИ, рдФрд░ рдпреВрдПрдордПрд▓ рдХрд╛ рдЬреНрдЮрд╛рди рд╢реАрд░реНрд╖ 7 рд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рд╣реЛ рдЧрдпрд╛ рд╣реИред
рд╢реНрд░реЗрдгрд┐рдпреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рдирд╛ рдФрд░ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдирд╛ рдХрд╛рдлреА рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдХрд┐ рдЙрдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЗрдВ рдХреМрди рд╕реЗ рдХреМрд╢рд▓ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдорд╛рдВрдЧ рдореЗрдВ рд╣реИрдВред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╢реНрд░реЗрдгреА рдЬреНрдЮрд╛рди рдХреЗ рд▓рд┐рдП, рд╕реНрдерд┐рддрд┐ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИ:
рдХреЛрдб рджреЗрдЦреЗрдВ tmp <- merge(x = all.skills, y = jobdf %>% select(id, lvl), by = "id", sort = FALSE) tmp <- na.omit(tmp) ggplot(as.data.frame(table(tmp %>% filter(category == "knowledge") %>% select(skill.group)))) + geom_bar(colour = "#666666", stat = "identity", aes(x = reorder(Var1, Freq), y = Freq, fill = reorder(Var1, -Freq))) + scale_y_continuous(name = " ") + theme(legend.position = "none", axis.text = element_text(size = 12)) + coord_flip()

рдЧреНрд░рд╛рдл рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛рдмреЗрд╕, рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдбреЗрд╡рд▓рдкрдореЗрдВрдЯ рдореЗрдердбреЛрд▓реЙрдЬреА рдФрд░ 1 рд╕реА рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдЬреНрдЮрд╛рди рдХреА рд╕рдмрд╕реЗ рдмрдбрд╝реА рдорд╛рдВрдЧ рд╣реИред рдЗрд╕рдХреЗ рдмрд╛рдж рд╕реАрдЖрд░рдПрдо, рдИрдЖрд░рдкреА-рд╕рд┐рд╕реНрдЯрдо рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреА рдореВрд▓ рдмрд╛рддреЗрдВ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдЬреНрдЮрд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред
рдЬрд╣рд╛рдВ рддрдХ тАЛтАЛрдорд╛рдирдХреЛрдВ рдХрд╛ рд╕рд╡рд╛рд▓ рд╣реИ, рдПрд╕рдХреНрдпреВрдПрд▓ рдФрд░ рдпреВрдПрдордПрд▓ рдХрд╛ рдЬреНрдЮрд╛рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдмрд╣реБрдд рдорд╛рдВрдЧ рдореЗрдВ рд╣реИ, рдПрдЖрд░рдЖрдИрдПрд╕ рд╕рдВрдХреЗрддрди рдЙрдирдХреА рдКрдБрдЪреА рдПрдбрд╝реА рдХреЗ рдЬреВрддреЗ рдХреЗ рд▓рд┐рдП рдЖрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди GOSTs рдХреЗрд╡рд▓ рдЫрдареЗ рд╕реНрдерд╛рди рдкрд░ рд╣реИрдВред
рдпрд╣рд╛рдБ рдХреЛрдб рд╣реИ ggplot(as.data.frame(table(tmp %>% filter(category == "standards") %>% select(skill.group)))) + geom_bar(colour = "#666666", stat = "identity", aes(x = reorder(Var1, Freq), y = Freq, fill = Var1)) + scale_y_continuous(name = " ") + theme(legend.position = "none", axis.text = element_text(size = 12)) + coord_flip()

рдкреНрд░рдпреБрдХреНрдд рдЙрдкрдХрд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдмрд╛рд░ рдлрд┐рд░ рд╕реЗ рдкреБрд╖реНрдЯрд┐ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд╕рд┐рд░ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХрд╛ рдореБрдЦреНрдп рдЙрдкрдХрд░рдг рд╣реИред рдХреЛрдИ рднреА рдПрдордПрд╕ рдСрдлрд┐рд╕ рд▓рд╛рдЗрди рдФрд░ рдЯрд╛рд╕реНрдХ рдЯреНрд░реИрдХрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рдмрд┐рдирд╛ рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╛рдХреА рдЙрд╕ рд╕рдВрдкрд╛рджрдХ рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝реА рдЪрд┐рдВрддрд╛ рдХрд╛ рд╡рд┐рд╖рдп рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдЕрдкрдиреА рдпреЛрдЬрдирд╛рдУрдВ рдпрд╛ рд╕реНрдХреЗрдЪ рдЗрдВрдЯрд░рдлреЗрд╕ рдореЙрдбрд▓ рдмрдирд╛рддрд╛ рд╣реИред
рдпрд╣рд╛рдБ рдХреЛрдб рд╣реИ ggplot(tmp %>% filter(category == "tools")) + geom_histogram(colour = "#666666", stat = "count", aes(skill.group, fill = skill.group)) + scale_y_continuous(name = " ") + theme(legend.position = "none", axis.text = element_text(size = 12)) + coord_flip()

рдЖрдп рдкрд░ рдХреМрд╢рд▓ рдХрд╛ рдкреНрд░рднрд╛рд╡
, , . , , , .
jobs.paid
all.skills
, data frame.
# 4.4 vizualize paid skills tmp <- na.omit(merge(x = all.skills, y = jobs.paid %>% select(id, salary, lvl, City), by = "id", sort = FALSE))
:
> head(tmp) id skill skill.group category salary lvl City 2 25781585 android mobile os knowledge 90000 middle 3 25781585 project management activities 90000 middle 5 25781585 project management activities 90000 middle 6 25781585 ios mobile os knowledge 90000 middle 7 25750025 aris aris standards 70000 middle 8 25750025 - business analysis activities 70000 middle
, .. . :
ggplotly(ggplot(tmp %>% filter(category == "activities"), aes(skill.group, salary)) + coord_flip() + geom_count(aes(size = ..n.., color = City)) + scale_fill_discrete(name = "") + scale_y_continuous(name = ", .") + scale_size_area(max_size = 11) + theme(legend.position = "bottom", axis.title = element_blank(), axis.text.y = element_text(size=10, angle=10)))

, BA/SA .
:
ggplot(tmp %>% filter(category == "personal", City %in% c("", "-")), aes(tools::toTitleCase(skill), salary)) + coord_flip() + geom_count(aes(size = ..n.., color = skill.group)) + scale_y_continuous(breaks = round(seq(min(tmp$salary), max(tmp$salary), by = 20000),1), name = ", .") + scale_size_area(max_size = 10) + theme(legend.position = "none", axis.title = element_text(size = 11), axis.text.y = element_text(size=10, angle=0))

, MS Office , тАФ , - . , , , .
, , : UML ARIS, SQL ( ) , IDEF тАФ , "".

, , , . , 1478 - key_skills. , - .
, data frame:
> jobdf$Responsibility[[1]] [1] "Training course in business analysis. тЧП Define needs of the user/client, understand the problem which needs to be solved. тЧП " > jobdf$Requirement[[1]] [1] "At least 6 months' experience in business analysis. тЧП Knowledge of qualitative methods such as usability testing, interviewing, focus groups. тЧП "
, , . URL' , .
hh.get.full.desrtion <- function(df) { df$full.description <- NA for (myURL in df$URL) { try( { data <- fromJSON(myURL) if (length(data$description) > 0) { df$full.description[which(df$URL == myURL, arr.ind = TRUE)] <- data$description } print(paste0("Filling in " , which(df$URL == myURL, arr.ind = TRUE) , " out of " , length(df$URL))) } ) } df$full.description <- tolower(df$full.description) return(df) }
- , html- ., gsub
:
remove.Html <- function(htmlString) { #remove html tags return(gsub("<.*?>", "", htmlString)) }
, , , , . data frame ( df), , df "id, skill.group, category".
skills.from.desc <- function(df, dictionary) { sk <- data.frame( id = numeric() , skill.group = character() , category = character() ) for (myskill in dictionary$skill) { category <- dictionary[dictionary$skill == myskill, "category"] mypattern <- paste0(na.omit(t(dictionary %>% filter(skill == myskill) %>% select(starts_with("syn")))), collapse = "|") if (nchar(mypattern) > 1) { mypattern <- paste0(c(myskill, mypattern), collapse = "|") } else { mypattern <- myskill } cond = grep(x = df$full.description, pattern = mypattern) tmp <- data.frame( id = df[cond, "id"], skill.group = rep(myskill, length(cond)), category = rep(category, length(cond)) ) sk <- rbind(sk, tmp) } return(sk) }
# 5 text analysis # 5.1 get full descriptions jobdf <- hh.get.full.description(jobdf) jobdf$full.description <- remove.Html(tolower(jobdf$full.description)) sk.from.desc <- skills.from.desc(jobdf, dict)
, ?
> head(sk.from.desc) id skill.group category 1 25638419 axure tools 2 24761526 axure tools 3 25634145 axure tools 4 24451152 axure tools 5 25630612 axure tools 6 24985548 axure tools > tmp <- as.data.frame(table(sk.from.desc$skill.group), col.names = c("Skill", "Freq")) > htmlTable::htmlTable(x = head(tmp[order(tmp$Freq, na.last = TRUE, decreasing = TRUE),], 20), rnames = FALSE, header = c("Skill", "Freq"), align = 'l', css.cell = "padding-left: .5em; padding-right: 2em;")

, ! Project management, key_skills, ( ).
, , key_skills -5.
, . 1478 , , key_skills, , .

, , BA , - .

, .
data frame , , . , -.
tmp <- na.omit(merge(x = sk.from.desc, y = jobs.paid %>% filter(City %in% c("", "-")) %>% select(id, salary, lvl, City), by = "id", sort = FALSE))
> head(tmp) id skill.group category salary lvl City 1 25243346 uml standards 160000 middle 2 25243346 requirements management activities 160000 middle 3 25243346 designing business processes activities 160000 middle 4 25243346 communication skills personal 160000 middle 5 25243346 mobile os knowledge 160000 middle 6 25243346 ms visio tools 160000 middle
, , , .
ggplotly(ggplot(tmp %>% filter(category == "activities"), aes(skill.group, lvl)) + geom_count(aes(color = salary, size = ..n..)) + scale_size_area(max_size = 13) + theme(legend.position = "right", legend.title = element_text(size = 10), axis.title = element_blank(), axis.text.y = element_text(size=10)) + coord_flip() + scale_color_continuous(labels = function(x) format(x, scientific = FALSE), breaks = round(seq(min(tmp$salary), max(tmp$salary), by = 70000),1), low = "blue", high = "red", name = ", ."))
?

-, , - . ( , , , .)
-, , "" -, .
, key_skills.

, , 150 .. UML ARIS, IDEF, , тАФ .
:

, - , , key_skills , . , 150 .. , .
?
, - :

, , , ? , . , , . , ├│ ( ) .
, - :

-
BA/SA ,
- . , ;
- ( ) 200 .. , , ;
- ;
- тАФ - ( , , )
key_skills
hh , ;- , , , (!) ;
- , -, UX ;
- . , - 150 ..;
- , , SQL, UML & ARIS. , .. . , , ,
.
wordcloud2::wordcloud2(data = table(sk.from.desc$skill.group), rotateRatio = 0.3, color = 'random-dark')
