-
Notifications
You must be signed in to change notification settings - Fork 3
/
blog_post.Rmd
1267 lines (1004 loc) · 57.7 KB
/
blog_post.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
title: "Analiza ofert pracy"
author: "Łukasz Prokulski"
date: "`r Sys.Date()`"
output:
html_document:
fig_align: center
fig_height: 8
fig_width: 10
self_contained: no
toc: yes
---
Ile jest pracy dla ludzi zajmujących się analizą danych i machine learningiem? Jakiej pracy w Polsce jest najwięcej? Czy widać podział na *Polskę A* i *Polskę B* w ofertach pracy?
Nie znalazłem żadnych raportów ani badań na ten temat. Największy (chyba) portal z ofertami pracy Pracuj.pl publikuje co jakiś czas **[raport](http://media.pracuj.pl/48161-rynek-pracy-specjalistow-2018-kogo-szukali-pracodawcy)**, ale to nie to. Już lepsze są wyniki **[ankiet prowadzonych przez Stackoverflow](https://insights.stackoverflow.com/survey/2018/)** ale to są dane globalne. Najbliższe temu czego szukałem były raporty np. [dla województwa łódzkiego](http://obserwatorium.wup.lodz.pl/index.php/analiza-tresci), ale najnowszy dotyczy wiosny 2015 roku (zresztą najnowsza aktualność na tej stronie to grudzień 2015...).
Łódzki raport robiło pięć osób, to co poniżej robiłem sam. Może więc mieć swoje niedoskonałości, ale mam nadzieję że będzie dla Was interesujący.
```{r document_setup, echo=FALSE, message=FALSE, error=FALSE, warning=FALSE}
library(tidyverse)
library(knitr)
library(kableExtra)
# chunks options
opts_chunk$set(message = FALSE, error = FALSE, warning = FALSE, echo = FALSE)
options(knitr.table.format = "html")
# skryp dodający tło do wykresów
source("/home/lemur/RProjects/!Rmarkdown_templates/da_plot.R")
```
# Metodologia i zebranie danych
Ponieważ wymieniony Pracuj.pl jest jednym z największych serwisów dane, które zostały przeanalizowane pochodzą z tego serwisu.
Proces polegał na zebraniu listy ogłoszeń (8 lutego), a następnie pobranie każdego z ogłoszeń z listy - ten proces trwał kilka dni. Tak zebrane ogłoszenia zostały podzielone na grupy, zgodnie z informacjami zawartymi w treści ogłoszeń lub opisujących ich metadanych:
* województwo
* poziom stanowiska
* poziom wynagrodzenia (tam gdzie ta informacja została umieszczona)
* kategoria pracy (w jakiej branży jest oferowana praca) - tutaj jedno ogłoszenie może należeć do kilku kategorii
W dalszej części analizowana jest również treść ofert pod kątem występujących w nich słów.
```{r}
#### Przygotowanie słowników ####
## biblioteki
# manipulacje danymi:
library(tidyverse)
# tekst:
library(tidytext)
# korelacja w długich tabelach
library(widyr)
# mapy
library(sf)
# tabele
library(knitr)
library(kableExtra)
## słowniki
# słowa
pl_stop_words <- read_lines("~/RProjects/!polimorfologik/polish_stopwords.txt")
stem_dict <- readRDS("~/RProjects/!polimorfologik/polimorfologik.RDS")
# mapa województw
poland_map <- read_sf("~/RProjects/!mapy_shp/wojewodztwa.shp") %>%
select(jpt_nazwa_, geometry)
# dane o ludności z GUS - https://bdl.stat.gov.pl/BDL/metadane/metryka/2137
poland_ludnosc <- read_csv("~/RProjects/!daneGUS/Ludnosc_wg_plci_wieku_2017.csv",
col_types = "cccc-i",
col_names = c("TERYT", "nazwa", "wiek", "plec", "liczba"),
skip = 1) %>%
filter(wiek %in% c( "20-24", "25-29", "30-34", "35-39", "40-44", "45-49", "50-54", "55-59", "60-64")) %>%
filter(str_to_lower(nazwa) %in% poland_map$jpt_nazwa_) %>%
group_by(nazwa) %>%
summarise(liczba = sum(liczba)) %>%
ungroup() %>%
mutate(nazwa = str_to_lower(nazwa))
# słowa związane z machine learning
ml_tags <- c("tensorflow", "pytorch", "nlp", "lstm", "cnn", "rnn", "spark", "hadoop", "hive", "python", "keras")
# słowa związane z IT
technologie <- c("java", "javascript", "apache", "basic", "vba", "excel", "access", "sql", "net", "git",
"sharepoint", "asp.net", "asp", "angular", "oracle", "html", "mvc", "web", "bpm", "css",
"php", "svn", "xml", "visual", "azure", "windows", "linux", "erp", "uml", "api", "flask",
"shiny", "aws", "ms", "word", "office", ml_tags)
#### Wczytanie i oczyszczenie danych ####
# szukamy najnowszego pliku ze zgromadzonymi danymi
offers <- list.files("data/") %>%
sort(decreasing = TRUE) %>%
.[[1]] %>%
paste0("data/", .) %>%
# i wczytujemy go
readRDS()
# funkcja rozbija tagi
make_tag_list <- function(x) {
str_split(x, ", ") %>% unlist() %>% unique()
}
# czyszczenie danych
offers <- offers %>%
distinct(i, .keep_all = TRUE) %>%
# poprawa pl-literek
mutate(localization = str_replace_all(localization, "ó", "ó"),
category = str_replace_all(category, "ó", "ó"),
company = str_replace_all(company, "ó", "ó"),
company = str_replace_all(company, "Ó", "Ó"),
company = str_replace_all(company, "&", "&"),
body = str_replace_all(body, "&", "&")) %>%
# dodanie kolumny z wojewodztwem
mutate(woj = str_split(localization, ", ") %>%
# wojewodztwo to ostatni czlon w lokalizaji
map_chr(.f = function(x) { x[[length(x)]] })) %>%
# dodanie kolumny listą tagów z kategorii
mutate(tag = map(category, make_tag_list)) %>%
mutate_at(.vars = vars(company, category, woj), .funs = str_trim) %>%
mutate(salary = str_replace_all(salary, " zł brutto", "")) %>%
mutate(salary = factor(salary,
levels = c("empty", "do 2 tys.", "2 - 4 tys.", "4 - 6 tys.", "6 - 8 tys.",
"8 - 10 tys.", "10 - 12 tys.", "12 - 15 tys.", "powyżej 15 tys."),
labels = c("empty", "do 2 tys.", "2-4 tys.", "4-6 tys.", "6-8 tys.",
"8-10 tys.", "10-12 tys.", "12-15 tys.", "powyżej 15 tys.")))
# tylko polskie oferty
# wojewodztwa, ktore mają małą literę na początku
offers_pl <- offers %>%
filter(str_sub(woj, 1, 1) != str_to_upper(str_sub(woj, 1, 1)) & woj != "zagranica")
# ile jest wszystkich ofert?
n_offers <- nrow(offers)
# ile jest polskich ofert?
n_pl_offers <- nrow(offers_pl)
# pełne oferty nie będą już potrzebne
rm(offers)
```
# Analiza
## Ogólna charakterystyka
Łącznie mamy `r n_pl_offers` ofert z pracą na terenie Polski (z `r n_offers` wszystkich). Dane zgromadzone zostały w dniach 8-12.02.2019 r.
### Liczba ofert według województwa
W pierwszej kolejności sprawdźmy w jakich województwach jest najwięcej ofert pracy.
```{r pracuj_01, fig.height = 8, fig.width = 8}
plt <- offers_pl %>%
select(woj) %>%
count(woj) %>%
left_join(poland_map, by = c("woj" = "jpt_nazwa_")) %>%
mutate(center = st_centroid(geometry)) %>%
ggplot() +
geom_sf(aes(geometry = geometry, fill = n), color = "gray75", show.legend = FALSE) +
geom_sf_label(aes(geometry = center, label = n), color = "black", fill = "white") +
scale_fill_viridis_c(option = "B") +
theme_minimal() +
theme(axis.text.x = element_blank(), axis.text.y = element_blank()) +
labs(title = "Liczba ofert pracy według województwa",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "")
da_plot(plt, blank_x = T, blank_y = T)
```
Nie ma wielkiego zaskoczenia - dominuje województwo mazowieckie, a w dalszej kolejności województwa z dużymi miastami (Dolny Śląsk, Małopolska, Wielkopolska czy Śląsk). To naturalne - tam gdzie mieszka więcej ludzi jest więcej miejsc pracy.
Liczba bezwzględna ofert może być myląca - sprawdźmy więc liczbę ofert w przeliczeniu na liczbę mieszkańców danego województwa:
```{r pracuj_02, fig.width = 8, fig.height = 8}
offers_count <- offers_pl %>%
select(woj) %>%
count(woj)
plt <- offers_count %>%
left_join(poland_map, by = c("woj" = "jpt_nazwa_")) %>%
left_join(poland_ludnosc, by = c("woj" = "nazwa")) %>%
mutate(p = 10000* n/liczba) %>%
mutate(center = st_centroid(geometry)) %>%
ggplot() +
geom_sf(aes(geometry = geometry, fill = p), color = "gray75", show.legend = FALSE) +
geom_sf_label(aes(geometry = center,
label = sprintf("%d (%.2f)", n, p)),
color = "black", fill = "white", size = 3) +
scale_fill_viridis_c(option = "B") +
theme_minimal() +
theme(axis.text.x = element_blank(), axis.text.y = element_blank()) +
labs(title = "Liczba ofert pracy według województwa",
subtitle = paste0("Opis na mapie: liczba ofert (liczba ofert na 10 tys. mieszkańców w wieku 20-64 lata)\nNa podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "")
da_plot(plt, blank_x = T, blank_y = T)
```
Tutaj widać, że Wielkopolska wyprzedza Śląsk, Pomorskie wyprzedza Małopolskę. Tak czy inaczej - im większe miasta w ramach województwa tym więcej pracy.
### Liczba ofert według kategorii
A jak wygląda liczba ofert w zależności od branży?
```{r pracuj_03, fig.height = 9, fig.width = 10}
offers_tags <- offers_pl %>%
unnest(tag) %>%
count(tag) %>%
mutate(p = 100*n/sum(n)) %>%
arrange(p)
plt <- offers_tags %>%
mutate(tag = fct_inorder(tag)) %>%
ggplot() +
geom_col(aes(tag, p), fill = "lightgreen", color = "gray50", size = 0.1) +
geom_text(aes(tag, p, label = sprintf("%.1f%%", p)),
color = "gray10", hjust = -0.1, vjust = "middle", size = 3) +
coord_flip() +
labs(title = "Liczba ogłoszeń według branży",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Procent zebranych ogłoszeń")
da_plot(plt)
```
Najwięcej pracy jest w sprzedaży (około 18.2%) i obsłudze klienta (13.4%). Może to wynikać z dwóch rzeczy:
* pracy w usługach jest po prostu najwięcej - mówił o tym już Kazik Staszewski w piosence "Wiek XX": *Tylko trochę ludności coś tam jeszcze produkuje. Cała reszta tylko usługuje oraz informuje.*
* rotacja na stanowiskach związanych ze sprzedażą lub obsługą klienta jest duża
W dalszej kolejności mamy Inżynierię (co jest dla mnie zaskoczeniem) oraz pracę fizyczną (to nie jest zaskoczenie). Ogólnie rzecz biorąc większy jest popyt na pracowników nisko i średnio wykwalifikowanych - pracy prostej jest dużo.
### Najpopularniejsze kategorie w województwach
Podzielimy kategorie oferowanej pracy według województw:
```{r pracuj_04, fig.width = 12, fig.height = 8}
offers_tag_woj <- offers_pl %>%
select(woj, tag) %>%
unnest(tag) %>%
count(woj, tag)
plt <- offers_tag_woj %>%
group_by(woj) %>%
mutate(n = 100*n/sum(n)) %>%
top_n(5, n) %>%
ungroup() %>%
ggplot() +
geom_col(aes(tag, n, fill = tag), show.legend = FALSE, color = "gray50", size = 0.1) +
geom_text(aes(tag, n, label = sprintf("%.1f%%", n), hjust = if_else(n < 15, -0.1, 1.1)),
color = "gray10", vjust = "middle", size = 4) +
coord_flip() +
facet_wrap(~woj, scales = "free_y") +
labs(title = "Najpopularniejsze branże według województw",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Procent ofert w województwie")
da_plot(plt)
```
Tutaj już widać ciekawostki:
* w województwach bez największych ośrodków miejskich (lubelskie, warmińsko-mazurskie, świętokrzyskie, podlaskie) prawie 1/3 ofert dotyczy sprzedaży , prawie 1/5 obsługi klienta
* mazowieckie, dolnośląskie i małopolskie to miejsca dla programistów (IT - Rozwój oprogramowania)
* liczba biurowców i znajdujących się w nich firm w Warszawie przekłada się na zapotrzebowanie na Administrację biurową
* inżynieria i produkcja to spory (łącznie około 1/6 ofert) kawałek toru na Śląsku
* pracę w Finansach i ekonomii można znaleźć w największych miastach: Warszawie, Poznaniu, Wrocławiu, Krakowie
* ciekawe jest Budownictwo w świętokrzyskim czy Bankowość w warmińsko-mazurskim
Jeśli spojrzymy na kolejne miejsca (bez top pięć branż w skali kraju: Sprzedaż, Obsługa klienta, Inżynieria, Praca fizyczna, IT - Rozwój oprogramowania) sytuacja wygląda jak na poniższym wykresie:
```{r pracuj_05, fig.width = 13, fig.height = 8}
plt <- offers_tag_woj %>%
group_by(woj) %>%
mutate(n = 100*n/sum(n)) %>%
ungroup() %>%
filter(!tag %in% c("Sprzedaż", "Obsługa klienta", "Inżynieria", "Praca fizyczna", "IT - Rozwój oprogramowania")) %>%
group_by(woj) %>%
top_n(5, n) %>%
ungroup() %>%
ggplot() +
geom_col(aes(tag, n, fill = tag), color = "gray50", size = 0.1, show.legend = FALSE) +
geom_text(aes(tag, n, label = sprintf("%.1f%%", n), hjust = if_else(n < 4, -0.1, 1.1)),
color = "gray10", vjust = "middle", size = 4) +
coord_flip() +
facet_wrap(~woj, scales = "free_y") +
labs(title = "Najpopularniejsze branże według województw (bez top 5 w skali kraju)",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Procent ofert w województwie")
da_plot(plt)
```
Możemy również na jednym obrazku zaprezentować najbardziej popularne branże w każdym z województw:
```{r pracuj_06, fig.width = 14, fig.height = 10}
plt <- offers_tag_woj %>%
group_by(woj) %>%
mutate(n = 100*n/sum(n)) %>%
ungroup() %>%
ggplot() +
geom_tile(aes(woj, tag, fill = n), color = "gray50", size = 0.1) +
geom_text(aes(woj, tag, label = round(n, 1))) +
scale_fill_distiller(palette = "YlOrBr") +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0)) +
labs(title = "Popularność branż w zależności od województwa",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "", fill = "Procent ofert w województwie")
da_plot(plt, legend_bottom = T)
```
Na powyższym obrazku procenty dla każdej kategorii w ramach województwa (kolumna) sumują się do 100%. Z ciekawostek należy wymienić przede wszystkim brak pracy w Public Relations w lubelskim, opolski, podkarpackim, warmińsko-mazurskim oraz zachodniopomorskim. Czyżby to wpływ tego, że centrale firm (i co za tym idzie działy PR czy marketingu) umiejscowione były głównie w Warszawie (tutaj mamy największy udział PR w ofertach z danego województwa)?
### Najpopularniejsze województwa dla kategorii
Spójrzmy na powyższą *mapę* w przekroju per branża - w jakim województwie jest najwięcej pracy dla prawników? A dla osób zajmujących się branżą e-commerce?
```{r pracuj_07, fig.width=16, fig.height=16}
plt <- offers_tag_woj %>%
group_by(woj) %>%
mutate(n = 100*n/sum(n)) %>%
ungroup() %>%
group_by(tag) %>%
mutate(p = 100*n/sum(n)) %>%
ungroup() %>%
left_join(poland_map, by = c("woj" = "jpt_nazwa_")) %>%
ggplot() +
geom_sf(data = poland_map, aes(geometry = geometry), fill = "white", color = "gray75") +
geom_sf(aes(geometry = geometry, fill = p), color = "gray75") +
scale_fill_viridis_c(option = "B") +
theme_minimal() +
theme(axis.text.x = element_blank(), axis.text.y = element_blank()) +
labs(title = "Liczba ofert pracy według województwa w podziale na branże",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "", fill = "Procent ofert pracy w województwie") +
facet_wrap(~tag)
da_plot(plt, blank_x = T, blank_y = T, legend_bottom = T)
```
Od razu rzuca się w oczy największy odsetek pracy we wspomnianym Public Relations w mazowieckim. Prawo oraz Media / Sztuka / Rozrywka również dominują na Mazowszu.
Finanse / Ekonomia oraz IT - Administracja najbardziej popularne są w mazowieckim i małopolskim - może to wynikać z położenia *[shared services](https://pl.wikipedia.org/wiki/Centrum_us%C5%82ug_wsp%C3%B3lnych)* w Krakowie i Warszawie.
### Praca w IT
Ponieważ niniejszy blog w gruncie rzeczy dotyczy analizy danych i programowania w narzędziach do tej analizy służących przyjrzymy się dokładniej tego typu ofertom. Na pierwszy ogień sprawdźmy w jakich województwach pracę znaleźć mogą ludzie związani z tworzeniem oprogramowania (nie tylko programiści - kategoria IT - Rozwój oprogramowania) oraz z administracją (IT - Administracja).
```{r pracuj_08, fig.height = 8, fig.width = 10}
plt <- offers_tag_woj %>%
filter(str_detect(tag, "IT - ")) %>%
ggplot() +
geom_col(aes(woj, n, fill = tag),
position = position_dodge(),
color = "gray50", size = 0.1) +
coord_flip() +
labs(title = "Liczba ofert pracy w IT według województwa",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Liczba ofert", fill = "Dziedzina:")
da_plot(plt, legend_bottom = T)
```
Te liczby widzieliśmy już wcześniej - dominuje mazowieckie, dolnośląskie i małopolskie. Jeśli szukasz pracy jako *informatyk* to są to najlepsze do tego województwa (a precyzyjniej mówiąc: ich stolice).
Ważna uwaga - widać (nie w tych danych) odpływ firm szukających pracowników IT z Pracuj.pl na rzecz innych, dedykowanych serwisów. Pracuj.pl jest serwisem ogólnobranżowym. Gdybym jako programista miał szukać pracy szukałbym w innych miejscach.
```{r}
offers_tag_woj %>%
filter(str_detect(tag, "IT - ")) %>%
group_by(tag) %>%
summarise(n = sum(n)) %>%
ungroup() %>%
mutate(p = round(100*n/sum(n), 1)) %>%
set_names(c("Kategoria oferty", "Liczba ofert", "Procent")) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"), font_size = 11)
```
2/3 ofert w ramach obu kategorii to praca dla ludzi związanych z rozwojem oprogramowania.
## Stanowiska
Kolejnym wymiarem jaki mamy w ofertach jest poziom stanowiska. Zobaczmy jakich pracowników (mniej czy bardziej doświadczonych?, do zarządzania czy do wykonywania codziennych zadań?) poszukuje się najwięcej:
```{r pracuj_09, fig.height = 5, fig.width = 8}
plt <- offers_pl %>%
count(grade) %>%
mutate(n = n/sum(n)) %>%
mutate(grade = fct_reorder(grade, n)) %>%
ggplot() +
geom_col(aes(grade, n), fill = "lightgreen", color = "gray50") +
geom_text(aes(grade, n, label = sprintf("%.1f%%", 100*n), hjust = if_else(n < 0.1, -0.1, 1.1)),
color = "gray10", vjust = "middle", size = 4) +
coord_flip() +
scale_y_continuous(labels = scales::percent) +
labs(title = "Liczba ogłoszeń według poziomu stanowiska",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Procent zebranych ogłoszeń")
da_plot(plt)
```
2/3 ofert to stanowiska dla osób po prostu wykonujących codzienną pracę (specjalistów). Dyrektorów czy prezesów raczej nie szuka się poprzez ogłoszenia na portalach (a bezpośrednio, chociażby na LinkedIn). Stanowisk kierowniczych też nie ma za wiele - kierownikiem zostaje się poprzez awans. Inna sprawa, że część ofert może być pracą o wymaganiach dla specjalisty, a w nazwie mieć "kierownik" (szczególnie w sprzedaży).
### Liczba stanowisk według poziomu w województwach
```{r pracuj_10, fig.height = 10, fig.width = 10}
plt <- offers_pl %>%
count(woj, grade, sort = T) %>%
group_by(woj) %>%
mutate(p = n/sum(n)) %>%
ungroup() %>%
group_by(grade) %>%
mutate(p = p/sum(p)) %>%
ungroup() %>%
left_join(poland_map, by = c("woj" = "jpt_nazwa_")) %>%
ggplot() +
geom_sf(data = poland_map, aes(geometry = geometry), fill = "white", color = "gray75") +
geom_sf(aes(geometry = geometry, fill = p), color = "gray75", show.legend = FALSE) +
scale_fill_viridis_c(option = "B") +
facet_wrap(~grade) +
labs(title = "Liczba ogłoszeń według poziomu stanowiska\nw poszczególnych województwach",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "")
da_plot(plt, blank_x = T, blank_y = T)
```
Tutaj jest w miarę *płasko*. Dla poziomów mało popularnych (Asystent czy Dyrektor/Prezes) dane są zachwiane. W każdym razie specjalistów i kierowników wszędzie szuka się po równo. Praktykanci najprościej mają w mazowieckim, ale może to wynikać z tego że tutaj pojawiają się ogłoszenia - w innych województwach nabór na praktyki może odbywać się bez udziału Pracuj.pl (np. bezpośrednio na uczelniach).
### Najpopularniejsze nazwy stanowisk
Wiemy jakie są najpopularniejsze branże (i gdzie), zobaczmy jak nazywają się poszczególne stanowiska:
```{r pracuj_11, fig.height = 8, fig.width = 10}
plt <- offers_pl %>%
mutate(title = str_to_lower(title)) %>%
count(title) %>%
mutate(n = n/sum(n)) %>%
top_n(20, n) %>%
mutate(title = fct_reorder(title, n)) %>%
ggplot() +
geom_col(aes(title, n), fill = "lightgreen", color = "gray50") +
geom_text(aes(title, n, label = sprintf("%.1f%%", 100*n)),
color = "gray10", hjust = 1.1, vjust = "middle", size = 4) +
coord_flip() +
scale_y_continuous(labels = scales::percent) +
labs(title = "Najpopularniejsze nazwy stanowisk",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Procent zebranych ogłoszeń")
da_plot(plt)
```
Większość z tych najpopularniejszych odnosi się do sprzedaży i w zasadzie znaczy to samo. Czym różni się *przedstawiciel handlowy* od *specjalisty ds. sprzedaży*? Albo *regionalny kierownik sprzedaży* od *key account managera*? Może tym, że ten pierwszy ma pod sobą jakiś zespół.
Zwróćcie uwagę, że wśród 20 najpopularniejszych nazw nie ma właściwie nikogo z IT. Zobaczmy zatem najpopularniejsze nazwy stanowisk w podziale na branże:
```{r}
offers_pl %>%
select(title, tag, i) %>%
unnest(tag) %>%
mutate(title = str_to_lower(title)) %>%
distinct(i, .keep_all = TRUE) %>%
count(title, tag) %>%
group_by(tag) %>%
mutate(p = 100*n/sum(n)) %>%
filter(n > 1) %>%
top_n(3, p) %>%
ungroup() %>%
arrange(tag, desc(p)) %>%
select(tag, title, n, p) %>%
mutate(p = round(p, 2)) %>%
set_names(c("Kategoria", "Nazwa stanowiska", "Liczba ofert", "Procent ofert w ramach kategorii")) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
font_size = 10) %>%
scroll_box(height = "300px")
```
Proszę zwrócić uwagę na kategorię *Badania i rozwój* (jeszcze się tutaj pojawi) - wśród najpopularniejszych są stanowiska związane z analizą danych.
W *Bankowości* mamy właściwie sprzedawców, podobnie w *Call Center*. W IT potrzebni są *informatycy* (w Administracji - czyli najpewniej ktoś z wsparcia użytkownika, help desk) lub programiści Java/.net.
### Jakie stanowiska dla IT/Machine Learning
Skoro w ramach kategorii *Badania i rozwój* pojawiają się stanowiska związane z analizą danych włączymy tę kategorię do przeglądu ofert związanych z IT. Najpopularniejsze stanowiska w tak poszerzonym obszarze to:
```{r pracuj_12, fig.height = 10, fig.width = 12}
plt <- offers_pl %>%
select(tag, title) %>%
unnest(tag) %>%
filter(str_detect(tag, "IT|Badania")) %>%
mutate(title = str_to_lower(title)) %>%
count(title, tag) %>%
group_by(tag) %>%
mutate(p = n/sum(n)) %>%
top_n(10, p) %>%
ungroup() %>%
mutate(title = fct_reorder(title, p)) %>%
ggplot() +
geom_col(aes(title, p), fill = "lightgreen", color = "gray50") +
geom_text(aes(title, p, label = sprintf("%.1f%% (%d)", 100*p, n)),
color = "gray10", hjust = 1.1, vjust = "middle", size = 4) +
coord_flip() +
facet_wrap(~tag, ncol = 1, scales = "free") +
scale_y_continuous(labels = scales::percent) +
labs(title = "Najpopularniejsze nazwy stanowisk w IT/Badania i rozwój",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Procent zebranych ogłoszeń w ramach kategorii")
da_plot(plt)
```
**PM / PO / Scrum master?**
W ramach rozwoju oprogramowania pojawiają się nie tylko developerzy, ale również *project manager*, a przy większej liczbie pokazanych nazw byłby też zapewne *scrum master* czy *product owner*. Sprawdźmy zatem jak wygląda popyt na role tego typu (w IT i badaniach):
```{r pracuj_13, fig.height = 15, fig.width = 10}
plt <- offers_pl %>%
filter(str_detect(str_to_lower(title), "scrum master|product owner|project manager|kierownik projektu")) %>%
unnest(tag) %>%
filter(str_detect(tag, "IT|Badania")) %>%
count(title, tag) %>%
group_by(title) %>%
mutate(s = sum(n)) %>%
ungroup() %>%
mutate(title = fct_reorder(title, s)) %>%
ggplot() +
geom_col(aes(title, n, fill = tag), color = "gray50") +
coord_flip() +
labs(title = "Liczba ogłoszeń według nazwy stanowiska\n(dla wybranych kategorii)",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Liczba ofert", fill = "Kategoria")
da_plot(plt, legend_bottom = T)
```
Słownik nazw stanowisk jest dość szeroki, ale gdyby sprowadzić nazwy stanowisk do podstawowych form (czyli: project manager, product owner, scrum master) dostaniemy:
```{r}
offers_pl %>%
filter(str_detect(str_to_lower(title), "scrum master|product owner|project manager|kierownik projektu")) %>%
mutate(title = str_to_lower(title)) %>%
select(title) %>%
mutate(title = case_when(
str_detect(title, "scrum master") ~ "scrum master",
str_detect(title, "product owner") ~ "product owner",
str_detect(title, "project manager|kierownik projektu") ~ "project manager",
TRUE ~ "pozostałe"
)) %>%
count(title, sort = T) %>%
set_names(c("Stanowisko (grupa)", "Liczba ofert")) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
font_size = 10)
```
**Data Analyst / Data Scientist / Data Engineer?**
Jak wygląda analogiczny słownik dla ofert związanych z przetwarzaniem i analizą danych?
```{r pracuj_14, fig.height = 11, fig.width = 13}
plt <- offers_pl %>%
filter(str_detect(str_to_lower(title), "data analyst|data scientist|data engineer")) %>%
unnest(tag) %>%
count(title, tag) %>%
group_by(title) %>%
mutate(s = sum(n)) %>%
ungroup() %>%
mutate(title = fct_reorder(title, s)) %>%
ggplot() +
geom_col(aes(title, n, fill = tag), color = "gray50") +
coord_flip() +
labs(title = "Liczba ogłoszeń według nazwy stanowiska\n(dla wybranych stanowisk)",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Liczba ofert", fill = "")
da_plot(plt, legend_bottom = T)
```
Dodatkowo widzimy tutaj (oznaczoną kolorem) branżę w której dane oferty występują. Zatem - jako adept sztuki analizowania danych powinieneś szukać pracy w ramach kategorii *Badania i rozwój*, pomimo że wydawałoby się, że pisanie skryptów w Pythonie to raczej *rozwój oprogramowania*. Ot pułapka :)
**W jakiej branży najłatwiej znaleźć pracę analitykowi danych?**
Podobnie jak dla PMów, PO i Scrum masterów sprowadźmy nazwy stanowisk do podstawowych form i sprawdźmy w jakiej kategorii ofert występują najczęściej:
```{r pracuj_15, fig.height = 6, fig.width = 9}
plt <- offers_pl %>%
select(title, tag) %>%
unnest(tag) %>%
mutate(title = str_to_lower(title)) %>%
filter(str_detect(title, "data analyst|data scientist|data engineer")) %>%
mutate(title = case_when(
str_detect(title, "data analyst") ~ "Data Analyst",
str_detect(title, "data scientist") ~ "Data Scientist",
str_detect(title, "data engineer") ~ "Data Engineer",
TRUE ~ "pozostałe"
)) %>%
count(title, tag, sort = T) %>%
ggplot() +
geom_tile(aes(tag, title, fill = n), color = "gray50", show.legend = FALSE) +
geom_text(aes(tag, title, label = n)) +
scale_fill_distiller(palette = "YlOrBr") +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0)) +
labs(title = "Liczba ogłoszeń według branży\ndla stanowisk związanych z Machine Learning",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "")
da_plot(plt)
```
Znowu: *badania i rozwój*. Rozwój oprogramowania jest na drugim miejscu. Widzimy też, że "data analyst" znajdzie prace w finansach - zapewne chodzi o przygotowywanie modeli scoringowych czy wykrywanie fraudów (np. na kartach).
## Zarobki
W przypadku **`r count(offers_pl, salary) %>% mutate(p = 100*n/sum(n)) %>% filter(salary == "empty") %>% pull(p) %>% round(2)` procent** ofert nie ma podanych informacji o proponowanych zarobkach. Zobaczmy jak to wygląda dla pozostałych.
```{r pracuj_16, fig.height = 6, fig.width = 10}
plt <- offers_pl %>%
count(salary) %>%
mutate(n = n/sum(n)) %>%
filter(salary != "empty") %>%
mutate(salary = fct_rev(salary)) %>%
ggplot() +
geom_col(aes(salary, n), fill = "lightgreen", color = "gray50") +
coord_flip() +
scale_y_continuous(labels = scales::percent) +
labs(title = "Procent ogłoszeń według podanego przedziału zarobków",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Procent zebranych ogłoszeń")
da_plot(plt)
```
Dominuje zakres 2-6 tys. brutto. Za chwilę zobaczymy trochę więcej informacji o zarobkach.
### Zarobki a poziom stanowiska
W ofertach zarobki podawane są jako przedziały oferowanej płacy brutto. Słupki słupkami, ale jak wyglądają zarobki w poszczególnych branżach?
```{r pracuj_17, fig.height = 4, fig.width = 10}
plt <- offers_pl %>%
filter(salary != "empty") %>%
count(salary, grade) %>%
group_by(grade) %>%
mutate(c = sum(n)) %>%
mutate(n = 100*n/sum(n)) %>%
ungroup() %>%
mutate(grade = paste0(grade, " (", c, ")")) %>%
ggplot() +
geom_tile(aes(salary, grade, fill = n), color = "gray50", show.legend = FALSE) +
geom_text(aes(salary, grade, label = sprintf("%.f%%", n))) +
scale_fill_distiller(palette = "YlOrBr") +
labs(title = "Procent ogłoszeń według stanowiska i poziomu zarobków\n(tylko oferty z podanym poziomem wynagrodzenia)",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "")
da_plot(plt)
```
Procentu sumują się do 100 w ramach wiersza. Przy nazwie poziomu stanowiska mamy liczbę ofert zawierających widełki płacowe dla tego poziomu - w niektórych przypadkach są to pojedyncze sztuki, zatem nie należy zbytnio uogólniać. Nie możemy więc powiedzieć, że 60% dyrektorów zarabia 8-10 tys. brutto. Po pierwsze, bo próbę ofert dla tychże dyrektorów mamy małą, a po drugie (i to chyba ważniejsze), bo dyrektorów nie szuka się na Pracuj.pl.
Ale rozkład dla specjalistów, asystentów czy praktykantów można traktować za dość prawdopodobny. Ciekawie wyglądają dwa jaśniejsze pola dla kierowników - jedno 4-6 tys. brutto, drugie 10-12 tys. brutto. Stawiam tezę, że pierwsza kwota jest dla stanowisk tak naprawdę specjalistycznych (w sensie zakresu obowiązków) ale *szumnie* nazwanych, a druga to rzeczywiste stanowiska kierownicze.
### Zarobki a województwo
Odejdźmy na chwilę od stanowisk i policzmy rozkład poziomu oferowanych zarobków w przekroju przez województwa.
```{r pracuj_18, fig.height = 8, fig.width = 10}
plt <- offers_pl %>%
filter(salary != "empty") %>%
count(salary, woj) %>%
group_by(woj) %>%
mutate(c = sum(n)) %>%
mutate(n = 100*n/sum(n)) %>%
ungroup() %>%
mutate(woj = paste0(woj, " (", c, ")")) %>%
arrange(desc(woj)) %>%
mutate(woj = fct_inorder(woj)) %>%
ggplot() +
geom_tile(aes(salary, woj, fill = n), color = "gray50", show.legend = FALSE) +
geom_text(aes(salary, woj, label = sprintf("%.f%%", n))) +
scale_fill_distiller(palette = "YlOrBr") +
labs(title = "Podział ogłoszeń według województwa i poziomu zarobków\n(tylko oferty z podanym poziomem wynagrodzenia)",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "")
da_plot(plt)
```
Widać to co widać też na innych tego typu zestawieniach (np. średnie zarobki w powiatach - takie dane powinny być w BDLu w GUSie). Lepiej (widać to głównie na liczbach z kolumn 2-4 tys. oraz 4-6 tys.) zarabia się w mazowieckim, dolnośląskim i Wielkopolsce. W pomorskim ponad połowa ofert to zarobki na poziomie 2-4 tys.
### Zarobki a branża
W której branży zarabia się najlepiej? Znowu - liczby w wierszu sumują się do 100%.
```{r pracuj_19, fig.height = 10, fig.width = 10}
plt <- offers_pl %>%
filter(salary != "empty") %>%
unnest(tag) %>%
count(salary, tag) %>%
group_by(tag) %>%
mutate(c = sum(n)) %>%
mutate(n = 100*n/sum(n)) %>%
ungroup() %>%
mutate(tag = paste0(tag, " (", c, ")")) %>%
arrange(desc(tag)) %>%
mutate(tag = fct_inorder(tag)) %>%
ggplot() +
geom_tile(aes(salary, tag, fill = n), color = "gray50", show.legend = FALSE) +
geom_text(aes(salary, tag, label = sprintf("%.f%%", n))) +
scale_fill_distiller(palette = "YlOrBr") +
labs(title = "Podział ogłoszeń według branży i poziomu zarobków\n(tylko oferty z podanym poziomem wynagrodzenia)",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y ="")
da_plot(plt)
```
Widać, że IT zarabia lepiej (w administracji 41% to oferty na poziomie 8-10 tys., w rozwoju oprogramowania 84% to od 8 tys. brutto w górę) niż obsługa klienta (41% dla 4-6 tys.).
Godnym uwagi jest kategoria *Franczyza / Własny biznes* - nie sądzę, że zarobki powyżej 15 tys. brutto to jest norma. Zapewne jest też tak, że wszyscy ci Dyrektorzy pochodzą właśnie z tej kategorii (sprawdź tabelkę wyżej).
Nie wiem czy zwróciliście uwagę na to, że pojawił nam się wcześniej całkiem liczny *kwadracik* **Specjalista 15k+**. Na jakich stanowiskach i w jakich firmach oferuje się takie widełki?
```{r}
offers_pl %>%
filter(grade == "Specjalista", salary == "powyżej 15 tys.") %>%
unnest(tag) %>%
count(tag, title, company) %>%
arrange(tag, company, desc(n)) %>%
set_names(c("Kategoria", "Nazwa stanowiska", "Firma", "Liczba ofert")) %>%
kable() %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"),
font_size = 10) %>%
scroll_box(height = "300px")
```
Są tam (znani z Wykopu) **programiści 15k+**.
## Treść ofert
Przejdźmy teraz do analizy treści ofert. Do tej pory przeanalizowaliśmy metadane opisujące oferty (lokalizację, poziom i nazwę stanowiska, branżę oraz proponowane zarobki), ale *mięso* jest w treści. Tutaj ukryte są wymagania czy też obowiązki.
### Słowa w opisach
Jakie słowa występują najczęściej? Treść wszystkich ogłoszeń została rozbita na pojedyncze słowa, sprowadzone do wersji podstawowych (słownik jest ułomny) i usunięto wszystkie liczby. Zostają nam najpopularniejsze:
```{r}
words <- offers_pl %>%
unnest_tokens("word", body, token = "words")
words_clean <- words %>%
# pl stop words
filter(!word %in% pl_stop_words) %>%
# angielskie stop words
filter(!word %in% stop_words$word) %>%
# liczby
filter(is.na(as.numeric(word))) %>%
# stemming słów
left_join(stem_dict, by = c("word" = "word")) %>%
# jeśli nie udało się znaleźc formy podstawowej to bierzemy oryginalne słowo
mutate(stem = if_else(is.na(stem), word, stem)) %>%
select(-word) %>%
rename(word = stem) %>%
filter(!is.na(word))
```
```{r pracuj_20,fig.height = 6, fig.width = 10}
plt <- words_clean %>%
count(word) %>%
top_n(50, n) %>%
mutate(word = fct_reorder(word, -n)) %>%
ggplot() +
geom_col(aes(word, n/n_pl_offers), fill = "lightgreen", color = "gray50", size = 0.1) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0)) +
labs(title = "Najpopularniejsze słowa w ofertach pracy",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Średnia częstość wystąpień słowa w ofercie")
da_plot(plt)
```
Aby oderwać się od bezwzględnych liczb policzyłem ile razy (średnio) dane słowo występuje w ofercie pracy. Najczęściej mówi się o **pracy** (*poszukujemy do pracy*, *do twoich zadań podczas pracy*, *dajemy możliwość pracy*, itd.) co nie jest zaskakujące.
Druga grupa to **umiejętności**, **znajomość** i **doświadczenie**, **wykształcenie** - czyli to, co potrafisz i co jest potrzebne. Najlepiej **mile widzieć** (czyli *mile widziane*).
Kolejne to **oferować**, **możliwość**, **pakiet** - czyli to co daje firma.
Czwarta grupa: **firma**, **dobry**, **zespół** - czyli o tym jaka to firma jest wspaniała i jaki zgrany zespół na Ciebie czeka.
Żadnych zaskoczeń. Wszystkie ogłoszenia są jednakowe. Dlatego wolę te, w który podane jest w punktach co masz robić, co masz umieć, ile dostaniesz. Plus *stack technologiczny*, ale to już kwestia branży. Osobiście nie interesuje mnie *bogaty pakiet benefitów* czy *możliwość rozwoju i szkoleń* (w to ostatnie to nie wierzę właściwie), a *zgrany, młody i dynamiczny zespół* to slogan.
#### Słowa związane z machine learning
Wróćmy do naszej *branży* (naszej = związanej z analizą i obróbką danych). Przygotowałem słownik kilkudziesięciu słów związanych z technologią oraz dodatkowo z danymi (ogólnie rzecz biorąc). Zobaczmy jakie występują najczęściej:
```{r pracuj_21, fig.height = 5}
plt <- words %>%
filter(word %in% ml_tags) %>%
count(word) %>%
mutate(word = fct_reorder(word, n)) %>%
ggplot() +
geom_col(aes(word, n), fill = "lightgreen", color = "gray50", size = 0.1) +
coord_flip() +
labs(title = "Najpopularniejsze słowa związane z machine learning\nw ofertach pracy",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "Liczba ofert")
da_plot(plt)
```
Python w analizie danych króluje. Dlaczego nie ma tutaj R? Z jednego podstawowego powodu - **R** pojawia się bardzo często, ale oznacza *rok* (np. z klauzuli o przetwarzaniu danych, która czasem pojawia się w treści oferty). Stąd trudno go wyłuskać. Ale spokojnie, do języka R jeszcze dojdziemy.
Poza Pythonem widać technologie do trzymania danych (jeśli można to tak uprościć) - Hadoop, Spark i Hive. Tensorflow dominuje nad pytorchem, widać też śladowe ilości sieci neuronowych (CNN, LSTM i RNN).
Rozszerzmy teraz słownik do większej liczby technologicznych słów oraz jednocześnie pogrupujmy stanowiska do Data Analyst, Data Engineer oraz Data Scientist. Gdzie używa się (to nieco uproszczone sformułowanie) jakich technologii?
```{r pracuj_22, fig.height = 10, fig.width = 8}
plt <- offers_pl %>%
select(i, title) %>%
mutate(title = str_to_lower(title)) %>%
filter(str_detect(title, "data analyst|data scientist|data engineer")) %>%
mutate(title = case_when(
str_detect(title, "data analyst") ~ "Data Analyst",
str_detect(title, "data scientist") ~ "Data Scientist",
str_detect(title, "data engineer") ~ "Data Engineer",
TRUE ~ "pozostałe"
)) %>%
left_join(words_clean, by = "i") %>%
filter(word %in% technologie) %>%
count(title.x, word, sort = T) %>%
group_by(title.x) %>%
mutate(n = 100*n/sum(n)) %>%
ungroup() %>%
arrange(desc(word)) %>%
mutate(word = fct_inorder(word)) %>%
ggplot() +
geom_tile(aes(title.x, word, fill = n), color = "gray50") +
geom_text(aes(title.x, word, label = sprintf("%.1f%%", n)), color = "black") +
scale_fill_distiller(palette = "YlOrBr") +
scale_x_discrete(position = "top") +
labs(title = "Popularność technologii w treści ofert\ndla stanowisk związanych z Machine Learning",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "", fill = "Procent ofert dla stanowiska")
da_plot(plt, legend_bottom = T)
```
Procenty do 100 sumują się w kolumnach.
* Inżynier danych powinien znać się na Azure, SQLu i Pythonie. Przyda się też Java i Hadoop
* Analityk danych będzie miał do czynienia z Office (tutaj pytanie czy nie chodzi w jakimś procencie ofert pisanych po angielski o *biuro* czy też *siedzibę firmy* a nie pakiet Microsoftu? mniejszy procent MS na to może wskazywać), SQL, Excel. To analityk excelowo-accessowy w banku, mówię Wam!
* Naukowiec to już ewidentnie Python, SQL, Spark, przetwarzanie tekstu (NLP), sieci (CNN, LSTM, RNN), jest też Shiny!
**Wiecie już czego się uczyć?**
#### Słowa IT w ofertach
Sprawdźmy w jakich kategoriach (branżach) pojawiają się słowa związane z IT (i machine learning):
```{r pracuj_24, fig.height = 8, fig.width = 12}
plt <- words %>%
filter(word %in% technologie) %>%
unnest(tag) %>%
mutate(tag = case_when(
tag %in% c("IT - Rozwój oprogramowania",
"IT - Administracja",
"Badania i rozwój",
"Internet / e-Commerce / Nowe media",
"Inżynieria",
"Administracja biurowa",
"Sprzedaż") ~ tag,
tag %in% c("Finanse / Ekonomia",
"Bankowość",
"Ubezpieczenia") ~ "Finanse\n(w tym bankowość\ni ubezpieczenia)",
tag %in% c("Obsługa klienta",
"Call Center") ~ "Obsługa klienta\ni Call Center",
TRUE ~ "pozostałe")) %>%
count(word, tag) %>%
ggplot() +
geom_col(aes(word, n, fill = tag), color = "gray10", size = 0.1,
position = position_fill()) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0)) +
scale_y_continuous(labels = scales::percent) +
labs(title = "Najpopularniejsze słowa związane z IT w ofertach pracy",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "", fill = "")
da_plot(plt, legend_bottom = T)
```
W kategorii *pozostałe* najlepiej sprawdza się MS Office z Wordem i Excelem, czasem Visual Basiciem (*mile widziana będzie znajomość...*).
* Oczywiście wszędzie najwięcej jest niebieskiego (tego odpowiedzialnego za Rozwój oprogramowania) - w końcu słowa dobrane są pod IT
* Ciekawe są Badania i rozwój (taki brązowy) - tutaj pojawiają się rzeczy związane z sieciami neuronowymi (w tym Tensorflow i Pytorch).
* Zielony odpowiedzialny za Internet i e-commerce jest tam gdzie są technologie webowe: HTML, PHP, JavaScript.
* Finanse (tutaj złączone z bankowością i ubezpieczeniami) to nadal model Access i Excel spięte VBA.
Wiedząc jakie słowa związane z IT i ML występują w ogłoszeniach pokuśmy się o przecięcie tych informacji. Weźmy oferty, w których występują słowa związane z machine learningiem i sprawdźmy jakie słowa związane w całym IT w nich występują:
```{r pracuj_23, fig.height = 8, fig.width = 12}
# ogłoszenia ze słowami związanymi z ML
ml_ids <- words %>% filter(word %in% ml_tags) %>% distinct(i) %>% pull(i)
# z jakimi innymi słowami występują słowa związane z ML
plt <- words_clean %>%
filter(i %in% ml_ids, word %in% technologie) %>%
unnest(tag) %>%
count(word, tag) %>%
group_by(word) %>%
mutate(t = sum(n)) %>%
ungroup() %>%
mutate(word = fct_reorder(word, -t)) %>%
ggplot() +
geom_col(aes(word, n, fill = tag), color = "gray50", size = 0.1) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0)) +
labs(title = "Najpopularniejsze słowa związane z IT\nw ofertach pracy zawierających słowa związane z ML",
subtitle = paste0("Na podstawie ", n_pl_offers, " ofert zgromadzonych z serwisu Pracuj.pl w dniach 8-12.02.2019 r."),
x = "", y = "", fill = "")
da_plot(plt, legend_bottom = T)
```
Znowu Python, SQL. Znajomość Linuxa. Platforma AWS czy Azure. Znajomość Git. Dodatkowo Hadoop czy Spark. Po raz kolejny: **wiecie czego się uczyć?**
### Jakie technologie występują razem?
Teraz ciekawostka. Policzmy współczynnik korelacji liczby wystąpień słów pomiędzy kategoriami i na tej podstawie określmy po 5 najbardziej pasujących do siebie:
```{r}
words_clean %>%
filter(word %in% technologie) %>%
unnest(tag) %>%
count(word, tag) %>%
pairwise_cor(word, tag, n, upper = T, diag = F) %>%
group_by(item1) %>%
top_n(5, correlation) %>%
arrange(item1, desc(correlation)) %>%
mutate(w = sprintf("<strong>%s</strong> (%.3f)", item2, correlation)) %>%
mutate(w2 = paste0(w, collapse = ", ")) %>%
ungroup() %>%
distinct(item1, w2) %>%
set_names(c("Słowo", "występuje z...")) %>%
kable(escape = FALSE) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"), font_size = 11) %>%
scroll_box(height = "300px")
```
Tabela może nie jest super prosta w odbiorze, więc na przykładzie: słowo *excel* występuje ze słowami *ms*, *word*, *office*, *vba* oraz *erp*, zaś liczby w nawiasie mówią o tym jak bardzo te słowa są ze sobą skorelowane (czyli w dużym uproszczeniu jak często występują razem).
### Podobieństwo technologii w IT na podstawie treści ofert
Przełóżmy taką tabelkę na wykres - to pozwoli na sprawdzenie każdej pary, a nie tylko tych najpopularniejszych:
```{r pracuj_25, fig.width = 16, fig.height = 10}
plt <- words_clean %>%
filter(i %in% ml_ids) %>%
filter(word %in% technologie) %>%
unnest(tag) %>%
count(word, tag) %>%
pairwise_cor(word, tag, n, upper = FALSE, diag = TRUE) %>%
arrange(desc(item2)) %>%
mutate(item2 = fct_inorder(item2)) %>%