EncuestasIT

Encuestas IT

Este es un analisís general de los datos de las encuestas recolectadas por el sitio http://www.encuestasit.com/ Los datos en crudo de las encuestas están disponibles en el sitio, en la sección de Preguntas Frecuentes. Todo el trabajo fue realizado con la autorización de los creadores del sitio encuestasIt

Los objetivos de este trabajo son:

Indice

TODO

Obtención de datos

URL datos en crudo de las encuestas: R URL_ENCUESTAS URL datos de tabulado de tablas auxiliares: R URL_TABLAS

Estos archivos se guardarán localmente en R FILE_ENCUESTAS y R FILE_TABLAS respectivamente.

# Descargamos los datos en crudo del sitio de encuestasIT
if(!file.exists(FILE_ENCUESTAS))
    download.file(URL_ENCUESTAS, FILE_ENCUESTAS)

# Descargamos la información de las tablas anexas
if(!file.exists(FILE_TABLAS))
    download.file(URL_TABLAS, FILE_TABLAS)

Preprocesado de datos

Los datos están en formato CSV. Se espera es que cada linea sea un regitro y cada atributo está separado por una ",".

Hasta la versión publicada al 23/02/2017 ocurre un problema grave en el formato del documento, ya que uno de los campos (Observaciones) es de texto libre y no se encuentra "sanitizado" por lo que dentro del mismo puden haber "," y saltos de linea, lo que arruina el formato del documento. Algo similiar ocurre con el campo Medio para buscar trabajo que tiene valores separados por ","

El 22/02/2017 se solicitó al responsable del sitio que la proxima exportación de información se haga usando otro delimitador que no sea "," para evitar estos problemas

Antes de levantar los datos en una tabla necesitamos preprocesar el documento para solucionar estos problemas.

# Levantamos el archico como un documento de texto
txtdata <- readLines(FILE_ENCUESTAS) 

# Quitamos todas las lineas en blanco, no tienen razon de ser en el archivo.
empty_lines = grepl('^\\s*$', txtdata)
txtdata = txtdata[! empty_lines]

# Quitamos los saltos de linea dentro de los comentarios
txtdata <- quitarSaltosLineaComentarios(txtdata)

# Quitamos los ", ," por ",," 
txtdata <- gsub(", ,", ",,", txtdata)
# y los ",  ," por ",,"
txtdata <- gsub(",  ,", ",,", txtdata)
# y los ", \r\n" por ","
txtdata <- gsub(", \r\n", ",\r\n", txtdata)
# y los ",  \r\n" por ","
txtdata <- gsub(",  \r\n", ",\r\n", txtdata)

# Quitamos los ",False, " y lo reemplazamos por ",False," (3 veces por si hay varios espacios)
txtdata <- gsub(",False, ", ",False,", txtdata)
txtdata <- gsub(",False,  ", ",False,", txtdata)
txtdata <- gsub(",False,   ", ",False,", txtdata)

# Quitamos los ",True, " y lo reemplazamos por ",True," (3 veces por si hay varios espacios)
txtdata <- gsub(",True, ", ",True,", txtdata)
txtdata <- gsub(",True,  ", ",True,", txtdata)
txtdata <- gsub(",True,   ", ",True,", txtdata)

# Quitamos los ", " y lo reemplazamos por " "
txtdata <- gsub(", ", " ", txtdata)

# Veamos cuantas lineas no tienen la cantidad de "," que esperamos que tengan
cantComasEsperadas <- cantidadComas(txtdata[1])
dataCantComas <- lapply(txtdata, cantidadComas)

# Buscamos los renglones que tienen más o menos comas de las esperadas
renglonesInconsistentes <- txtdata[dataCantComas != cantComasEsperadas]
renglonesConsistentes <- txtdata[dataCantComas == cantComasEsperadas]

Cantidad de renglones total: R length(txtdata) Cantidad de renglones inconsistentes: R length(renglonesInconsistentes) Cantidad de renglones consistentes: R length(renglonesConsistentes)

Vemos que existen muchos registros que no se pueden formatear bien.

Queda como mejora revisar estos registros para darle el correcto formato.

# Grabamos el procesado que hicimos hasta ahora
write(renglonesInconsistentes, "./datos/encuestas_unclear.txt")
write(renglonesConsistentes, "./datos/encuestas_clear.txt")

Carga de datos en memoria

Levantamos los datos en un DataFrame con el nombre encuestas De aquí en más la variable encuestas será nuestra set de datos principal

# ----------------------  Levantar DataFrame  ----------------------

# Levantamos el archivo ya formateado, 
encuestas <- read.csv("./datos/encuestas_clear.txt", quote = "")

Tratamiento de valores faltantes

Antes de seguir debemos analisar los valores faltantes (NA) en nuestra tabla

# ----------------------  Tratamiento Valores Faltantes  ----------------------

# Analisamos valores faltantes
na_count <- sapply(encuestas, function(y) sum(length(which(is.na(y)))))
na_count <- data.frame(na_count)
na_count <- subset(na_count, na_count > 0)
kable(na_count, caption="Cantidad de valores faltantes por columna")
na_count
MedioParaBuscarTrabajo 4
NivelRemunerativo 14136
SalarioActualBruto 22081
IdArea 22083
# Quitamos las columnas que tienen todos NA 
encuestas$SalarioActualBruto <- NULL
encuestas$IdArea <- NULL

# La columna "MedioParaBuscarTrabajo" no va a formar parte del analisis, pues no interesa en principio.
encuestas$MedioParaBuscarTrabajo <- NULL

# La mayoria de los datos de la columna NivelRemunerativo son NA, y sumado a que tampoco hay
# referencias sobre ese campo, lo mejor parece ser que es quitarlo
encuestas$NivelRemunerativo <- NULL


# Analisamos valores faltantes nuevamente
na_count <- sapply(encuestas, function(y) sum(length(which(is.na(y)))))
na_count <- data.frame(na_count)
na_count <- subset(na_count, na_count > 0)
kable(na_count, caption="Cantidad de valores faltantes por columna")

Table: Cantidad de valores faltantes por columna

na_count

Con esto ya no tenemos valores faltantes en nuestro DataSet.

Filtrado de datos: Solo incluimos Argentina.

Restringimos el dominio del analisís a Argentina. Para este analisís nos centraremos en los datos de un solo país.

Eventualmente esto puede cambiar. En una primera versión del analisís nos limitaremos a Argentina. Se puede cambiar esto para que el analisís sea con datos de otro país, pero hay fenomenos monetarios que son propios de cada nación (inflación, tipo de cambio) que deben ser analisados en detalle en cada caso

# Nos quedamos solo con los de Argentina, ya que para este estudio no nos interesa el resto. 
# Ademas sus salarios están expresados en moneda local de cada país, lo que requeriria una conversión
# Por el momento el estudio se basará en los datos de Argentina
encuestas <- subset(encuestas, IdPais == 1)
encuestas$IdPais <- NULL

Ajuste de tipos de dato

Antes de seguir debemos ajustar algunos tipos de datos. Las fechas las vamos a trabajar como POSIXlt. Los valores tabulados vamos a setearlos como Factors usando las tablas auxiliares.

# ----------------------  Ajuste de tipos de datos  ----------------------

# Pasamos la fecha al formato correcto
encuestas$Fecha <- as.character(encuestas$Fecha)
encuestas$Fecha <- as.POSIXlt(encuestas$Fecha)


# Levantamos las tablas auxiliares
tabla_sexo <- read.table(FILE_TABLAS, header = TRUE, sep=",", nrows =3, comment.char = "-")
tabla_nivel_educativo <- read.table(FILE_TABLAS, header = TRUE, sep="\t", nrows = 10, skip=7, comment.char = "-")
tabla_tipo_empresa <- read.table(FILE_TABLAS, header = TRUE, sep="\t", nrows = 7, skip=20, comment.char = "-")
tabla_provincia <- read.table(FILE_TABLAS, header = TRUE, sep="\t", nrows = 413, skip=30)
tabla_puesto <- read.table(FILE_TABLAS, header = TRUE, sep="\t", nrows = 95, skip=446)
tabla_tecnologia <- read.table(FILE_TABLAS, header = TRUE, sep="\t", nrows = 72, skip=544)

# Quitamos las provincias que no sean de argentina
tabla_provincia <- tabla_provincia[tabla_provincia$IdPais == 1, ]

# Seteamos los factors

encuestas$IdSexo <- factor(encuestas$IdSexo, levels = tabla_sexo$IdSexo, labels = tabla_sexo$Nombre)
kable(as.data.frame(table(encuestas$IdSexo)), caption="Cantidad de registros por sexo")
Var1 Freq
No informa 1530
Masculino 14411
Femenino 1933
encuestas$IdNivelEducativo <- factor(encuestas$IdNivelEducativo, levels = tabla_nivel_educativo$IdNivelEducativo, labels = tabla_nivel_educativo$Nombre)
kable(as.data.frame(table(encuestas$IdNivelEducativo)), caption="Cantidad de registros por nivel educativo")
Var1 Freq
No informa 305
Primario 33
Secundario en curso o incompleto 190
Secundario completo 1159
Terciario en curso o incompleto 1392
Terciario completo 3428
Universitario en curso o incompleto 6031
Universitario completo 3808
Master o postgrado en curso o incompleto 877
Master o postgrado completo 651
encuestas$IdTipoDeEmpresa <- factor(encuestas$IdTipoDeEmpresa, levels = tabla_tipo_empresa$IdTipoDeEmpresa, labels = tabla_tipo_empresa$Nombre)
kable(as.data.frame(table(encuestas$IdTipoDeEmpresa)), caption="Cantidad de registros por tipo de empresa")
Var1 Freq
No informa 1741
Una empresa privada 14307
Un organismo estatal 983
Una ONG 72
Otro 443
Mi propia empresa 308
Soy independiente / freelance 20
encuestas$IdProvincia <- factor(encuestas$IdProvincia, levels = tabla_provincia$IdProvincia, labels = tabla_provincia$Nombre)
kable(as.data.frame(table(encuestas$IdProvincia)), caption="Cantidad de registros por provincia")
Var1 Freq
Capital Federal 5693
GBA Zona Norte 256
GBA Zona Oeste 65
GBA Zona Sur 48
Costa Atlántica 15
Buenos Aires 7913
Catamarca 16
Córdoba 1685
Chaco 76
Chubut 48
Corrientes 104
Entre Ríos 114
Formosa 19
Jujuy 26
La Pampa 15
La Rioja 8
Misiones 99
Mendoza 335
Neuquén 163
Río Negro 74
Salta 42
Santa Cruz 20
Santiago del Estero 18
Sante Fe 710
San Juan 52
San Luis 65
Tierra del Fuego 13
Tucumán 182
encuestas$IdPuesto <- factor(encuestas$IdPuesto, levels = tabla_puesto$IdPuesto, labels = tabla_puesto$Nombre)
kable(as.data.frame(table(encuestas$IdPuesto)), caption="Cantidad de registros por puesto")
Var1 Freq
Desarrollador de software / Programador 4659
Arquitecto 379
Lider de Proyecto 1212
Analista Funcional 1203
Selector de personal TI 111
Diseñador Web 209
Investigación 46
Consultor TI 885
Administrador de Base de Datos 326
Administrador de Redes 299
Analista de Garantía de Calidad (QA) 353
Analista de Seguridad Informática 171
Auditor 87
Comercial de TI 147
Director de Sistemas 194
Documentador de Sistemas 4
Gerente de Proyectos 538
Implementador de Sistemas 252
Instructor 26
Gerente de Compras TI 8
Gerente de Comunicaciones 43
Gerente de Desarrollo 309
Gerente de Operaciones 155
Gerente de Seguridad Informática 71
Gerente de Sistemas 630
Gerente de Tecnología 340
Gerente de Ventas TI 46
Pasante 65
Mesa de Ayuda (Help Desk) 168
Soporte Técnico 771
Pasante (Trainee) 97
Otro 526
Administrador de Almacenamiento (Storage) 505
Administrador Middleware 17
Administrador de Sistemas 434
Administrador de Ambientes 703
Administrador de Servidores 482
Coordinador de Grupo 155
Lider Técnico 445
Comprador TI 14
Data Entry 23
Soporte de Aplicación 96
Soporte de Posventa 17
Jefe de Mesa de Ayuda 38
Operador NOC 49
Líder de Mesa de Ayuda 21
Líder de Operaciones 50
Líder de Garantía de Calidad (QA) 102
Líder de Seguridad Informática 41
Líder de Soporte Técnico 101
Operador de AS400 8
Preventa 33
Ejecutivo de Cuenta 46
Gerente de Producto 59
Analista BI 24
Scrum Master 5
Auditor de TI 7
Gerente General 12
Director General 12
Administrador de Backup 1
Maquetador 6
Administrador de Proyectos 13
Operador de Sistemas 1
Tester Funcional 10
Analista de Testeo 13
Jefe de Compras TI 0
Jefe de Comunicaciones 0
Jefe de Desarrollo 0
Jefe de Operaciones 0
Jefe de Seguridad Informática 1
Jefe de Sistemas 0
Jefe de Tecnología 0
Jefe de Ventas TI 0
Jefe de Gestión de Demanda 0
Diseñador Multimedia 0
Gestor de Cambios de IT 0
Gestor de Transición 0
Gestor de Configuraciones 0
Analista de Cambios 0
Gerente de Procesos de IT 0
Gestor de Incidentes 0
Gestor de Problemas 0
Gerente de Demanda 0
Gerente de Infraestructura 0
Jefe de Infraestructura 0
Supervisor de Infraestructura 0
Responsable de Infraestructura 0
Analista de Gestión de la Demanda 0
Responsable de Gestión de la Demanda 0
Analista de Procesos 0
Responsable de Procesos 0
Gestor de Servicios 0
Desarrollador BI 0
Lider BI 0
Gerente Regional de IT 0
encuestas$IdTecnologiaPrincipal <- factor(encuestas$IdTecnologiaPrincipal, levels = tabla_tecnologia$IdTecnologiaPrincipal, labels = tabla_tecnologia$Nombre)
## Warning in `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels)
## else paste0(labels, : duplicated levels in factors are deprecated
kable(as.data.frame(table(encuestas$IdTecnologiaPrincipal)), caption="Cantidad de registros por tecnología principal")
## Warning in `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels)
## else paste0(labels, : duplicated levels in factors are deprecated
Var1 Freq
.Net 3996
Java 2374
PHP 1063
C++ 203
C 94
Ruby 56
Perl 31
Prolog 0
Smalltalk 62
Python 96
Delphi 135
VisualBasic 267
ActionScript 46
Javascsript 144
Asp 69
Html 111
Haskell 1
MSSQLServer 554
Oracle 1054
PostgreSql 33
DatawareHousing 143
Cobol 200
DB2 25
SAP 969
Siebel 90
Otro 1504
Windows 2532
Linux 517
Solaris 36
Aix 52
Hp-ux 24
Mainframe 118
AS/400 144
Assembler 5
CMS 13
Cobol 0
Siebel 0
ERP 186
Flash 7
Flex 21
Meta4 7
RPG 14
Hp 62
Unix 183
Clipper 10
Genexus 89
MySql Server 69
Visual FoxPro 65
Android 73
Sharepoint 66
Clarion 24
QlikView 32
Microstrategy 38
BusinessObject 15
Cognos 14
Hyperion 2
Tibco 5
Board 0
Pentaho 5
CISCO 45
SSIS 2
VMWare 46
PowerBuilder 8
CRM 9
Objective-C 7
JD Edwards 4
PeopleSoft 5
Joomla 0
Clojure 0
Scala 0
Node js 0
Ruby on Rails 0
encuestas$TrabajaDesdeCasa <- factor(encuestas$TrabajaDesdeCasa, levels = c("True", "False"), labels = c("Si", "No"))
kable(as.data.frame(table(encuestas$TrabajaDesdeCasa)), caption="Cantidad de registros por trabaja desde casa")
Var1 Freq
Si 3108
No 14766
encuestas$LeGustaTrabajarDesdeCasa <- factor(encuestas$LeGustaTrabajarDesdeCasa, levels = c("True", "False"), labels = c("Si", "No"))
kable(as.data.frame(table(encuestas$LeGustaTrabajarDesdeCasa)), caption="Cantidad de registros por le gusta trabajar desde casa")
Var1 Freq
Si 11651
No 6223
encuestas$CambioPorMejorSalario <- factor(encuestas$CambioPorMejorSalario, levels = c("True", "False"), labels = c("Si", "No"))
kable(as.data.frame(table(encuestas$CambioPorMejorSalario)), caption="Cantidad de registros por cambiaria por mejor salario")
Var1 Freq
Si 14115
No 3759
encuestas$CambioPorMejorAmbiente <- factor(encuestas$CambioPorMejorAmbiente, levels = c("True", "False"), labels = c("Si", "No"))
kable(as.data.frame(table(encuestas$CambioPorMejorAmbiente)), caption="Cantidad de registros por cambiaria por ambiente")
Var1 Freq
Si 4829
No 13045
encuestas$CambioPorFormaDeTrabajo <- factor(encuestas$CambioPorFormaDeTrabajo, levels = c("True", "False"), labels = c("Si", "No"))
kable(as.data.frame(table(encuestas$CambioPorFormaDeTrabajo)), caption="Cantidad de registros por cambiaria por forma de trabajo")
Var1 Freq
Si 7797
No 10077
encuestas$CambioPorTecnologia <- factor(encuestas$CambioPorTecnologia, levels = c("True", "False"), labels = c("Si", "No"))
kable(as.data.frame(table(encuestas$CambioPorTecnologia)), caption="Cantidad de registros por cambiaria por tecnología")
Var1 Freq
Si 5173
No 12701
encuestas$CambioPorCercania <- factor(encuestas$CambioPorCercania, levels = c("", "True", "False"), labels = c("No informa", "Si", "No"))
kable(as.data.frame(table(encuestas$CambioPorCercania)), caption="Cantidad de registros por cambiaria por cercania")
Var1 Freq
No informa 4622
Si 3381
No 9870
encuestas$CambioPorMenorCargaHoraria <- factor(encuestas$CambioPorMenorCargaHoraria, levels = c("", "True", "False"), labels = c("No informa", "Si", "No"))
kable(as.data.frame(table(encuestas$CambioPorMenorCargaHoraria)), caption="Cantidad de registros por cambiaria por menor carga horaria")
Var1 Freq
No informa 4622
Si 3087
No 10165
encuestas$CambioPorOportunidadDeCarrera <- factor(encuestas$CambioPorOportunidadDeCarrera, levels = c("", "True", "False"), labels = c("No informa", "Si", "No"))
kable(as.data.frame(table(encuestas$CambioPorOportunidadDeCarrera)), caption="Cantidad de registros por cambiaria por oportunidad de carrera")
Var1 Freq
No informa 4622
Si 7333
No 5919
encuestas$TienePersonasACargo <- factor(encuestas$TienePersonasACargo, levels = c("", "True", "False"), labels = c("No informa", "Si", "No"))
kable(as.data.frame(table(encuestas$TienePersonasACargo)), caption="Cantidad de registros por tiene personas a cargo")
Var1 Freq
No informa 6172
Si 2869
No 8814

Limpieza de valores anomalos

# ---------------------- Limpieza de valores anomalos  ---------------------- 

# todas las (edad > 65) las vamos a considerar anomalas y vamos a desechar esos registros
encuestas <- encuestas[encuestas$Edad < 66, ]
hist(encuestas$Edad)
rug(encuestas$Edad)

# todas las (horas trabajadas >= 120 o <= 18) las vamos a considerar anomalas y vamos a desechar esos registros
encuestas <- encuestas[encuestas$horasTrabajadasXSemana < 120, ]
encuestas <- encuestas[encuestas$horasTrabajadasXSemana > 18, ]
hist(encuestas$horasTrabajadasXSemana)
rug(encuestas$horasTrabajadasXSemana)

# todos los (meses en el puesto actual >= 360) los vamos a considerar anomalas y vamos a desechar esos registros
encuestas <- encuestas[encuestas$MesesEnElPuestoActual < 480, ]
hist(encuestas$MesesEnElPuestoActual)
rug(encuestas$MesesEnElPuestoActual)

# todos los (salario actual neto >= 150000) los vamos a considerar anomalas y vamos a desechar esos registros
encuestas <- encuestas[encuestas$SalarioActualNeto < 150000, ]
hist(encuestas$SalarioActualNeto)
rug(encuestas$SalarioActualNeto)

# todos los (salario ideal neto >= 150000) los vamos a considerar anomalas y vamos a desechar esos registros
encuestas <- encuestas[encuestas$SalarioIdealNeto < 150000, ]
hist(encuestas$SalarioIdealNeto)
rug(encuestas$SalarioIdealNeto)

# Borramos los levels que no se usan
encuestas <- droplevels(encuestas)
## Warning in `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels)
## else paste0(labels, : duplicated levels in factors are deprecated

Creación de caracteristicas

# ---------------------- Creación de caracteristicas  ---------------------- 

encuestas$DiferenciaSalarioRealIdeal <- encuestas$SalarioIdealNeto - encuestas$SalarioActualNeto

encuestas$SalarioNetoPorHora <- encuestas$SalarioActualNeto / encuestas$horasTrabajadasXSemana

# Carga laboral: En relación a las horas que dedica al trabajo
encuestas$CargaLaboral <- cut(encuestas$horasTrabajadasXSemana, 5, labels = c("Part Time", "Full Time", "Extra Time", "Very Extra Time", "Extreme Time"))

# Antiguedad: Nivel de antiguedad en el actual trabajo
encuestas$Antiguedad <- cut(encuestas$MesesEnElPuestoActual,quantile(encuestas$MesesEnElPuestoActual,(0:4)/4), labels = c("Junior", "SemiSenior", "Senior", "Expert"))

# Experiencia: Nivel de antiguedad en cualquier trabajo
encuestas$Experiencia <- cut(encuestas$MesesDeExperiencia,quantile(encuestas$MesesDeExperiencia,(0:4)/4), labels = c("Junior", "SemiSenior", "Senior", "Expert"))

Limpieza de valores anomalos en caracteristicas creadas

# ---------------------- Limpieza de valores anomalos en caracteristicas creadas  ---------------------- 

# Todas las diferencias de salario real e ideal mayores a 25000 y menores a -5000 las eliminamos
# Por considerarlas anomalas.
encuestas <- encuestas[encuestas$DiferenciaSalarioRealIdeal < 25000, ]
encuestas <- encuestas[encuestas$DiferenciaSalarioRealIdeal > -5000, ]
hist(encuestas$DiferenciaSalarioRealIdeal)
rug(encuestas$DiferenciaSalarioRealIdeal)

# Todos los salarios netos por hora mayores a 1500 los vamos a eliminar por considerarlos anomalos
encuestas <- encuestas[encuestas$SalarioNetoPorHora < 1500, ]
hist(encuestas$SalarioNetoPorHora)
rug(encuestas$SalarioNetoPorHora)

# Todos los "Extreme Time" los vamos a borrar por no ser representativos
encuestas <- encuestas[encuestas$CargaLaboral != "Extreme Time", ]
table(encuestas$CargaLaboral)
## 
##       Part Time       Full Time      Extra Time Very Extra Time 
##            1580           14515             314              48 
##    Extreme Time 
##               0
# Borramos los levels que no se usan
encuestas <- droplevels(encuestas)

Exploración grafica

Algunos graficos de ejemplo:

# distribución de sueldo netos por hora en función del puesto
par(mar=c(3,18,1,1))
bymedian <- with(encuestas, reorder(IdPuesto, -SalarioNetoPorHora, median))
boxplot(SalarioNetoPorHora ~ bymedian, encuestas, horizontal = TRUE, las = 2, col="green")

# distribución de sueldo netos por hora en función del nivel educativo
par(mar=c(3,15,1,1))
bymedian <- with(encuestas, reorder(IdNivelEducativo, -SalarioNetoPorHora, median))
boxplot(SalarioNetoPorHora ~ bymedian, encuestas, horizontal = TRUE, las = 2, col="green")

# distribución de sueldo netos por hora en función del sexo
par(mar=c(3,10,1,1))
bymedian <- with(encuestas, reorder(IdSexo, -SalarioNetoPorHora, median))
boxplot(SalarioNetoPorHora ~ bymedian, encuestas, horizontal = TRUE, las = 2, col="green")

# distribución de sueldo netos por hora en función de las horas trabajadas por semana
par(mar=c(3,8,1,1))
bymedian <- with(encuestas, reorder(CargaLaboral, -SalarioNetoPorHora, median))
boxplot(SalarioNetoPorHora ~ bymedian, encuestas, horizontal = TRUE, las = 2, col="green")

# distribución de sueldo netos por hora en función de la experiencia
par(mar=c(3,7,1,1))
bymedian <- with(encuestas, reorder(Experiencia, -SalarioNetoPorHora, median))
boxplot(SalarioNetoPorHora ~ bymedian, encuestas, horizontal = TRUE, las = 2, col="green")

# distribución de sueldo netos por hora en función de la antiguedad
par(mar=c(3,7,1,1))
bymedian <- with(encuestas, reorder(Antiguedad, -SalarioNetoPorHora, median))
boxplot(SalarioNetoPorHora ~ bymedian, encuestas, horizontal = TRUE, las = 2, col="green")

# distribución de sueldo netos por hora en función de la tecnologia
par(mar=c(3,7,1,1))
bymedian <- with(encuestas, reorder(IdTecnologiaPrincipal, -SalarioNetoPorHora, median))
boxplot(SalarioNetoPorHora ~ bymedian, encuestas, horizontal = TRUE, las = 2, col="green")