• No se han encontrado resultados

4. Crear y modificar variables - 4 ullrtoolbox Crear y modificar variables

N/A
N/A
Protected

Academic year: 2019

Share "4. Crear y modificar variables - 4 ullrtoolbox Crear y modificar variables"

Copied!
25
0
0

Texto completo

(1)

49

4. Crear y modificar variables

El análisis estadístico correcto de las bases de datos pasa casi inevitablemente por crear nuevas variables y o modificar la naturaleza, escala, nombre o tipo de algunas de las existentes. Así podemos tener recogida la variable edad de los participantes en una

investigación pero podemos en un momento dado necesitar una versión discretizada de la misma en grupos de edad como infancia, adolescencia y adultez. En otras ocasiones

lo que deseamos es una recodificación de la variable de forma que ciertos valores extremos o inusuales observados para algún o algunos sujetos pasen a ser perdidos por el sistema (NA),

impidiendo así que estos puedan formar parte de los diferentes estadísticos y análisis que realicemos con dicha variable una vez recodificada. En contextos de investigación multivariada el usuario puede necesitar con una nueva variable que resulte del promedio de otras incluidas en la investigación. En resumen la tarea de crear y modificar variables ocupará una parte importante del tiempo invertido en el análisis de bases de datos. Por ese motivo hemos desarrollado un grupo de funciones que lo permitan de forma rápida y sencilla.

Cambiar el nombre de las variables

Con cambia.nombre.var.fnc podemos cambiar el nombre de una variable o múltiples

variables de forma simultánea.

datos = cambia.nombre.var.fnc(OBrienKaiser, antiguo=c('treatment','gender'), nuevo=c('tratamiento','sexo') )

datos = cambia.nombre.var.fnc(OBrienKaiser, c('treatment','gender'),

c('tratamiento','sexo') )

datos = cambia.nombre.var.fnc(OBrienKaiser, 1:2, c('tratamiento','sexo') )

Tres formas de renombrar las dos variables con idéntico resultado. Utilizando los nombres de las variables a modificar y sus argumentos (antiguo, nuevo). Sin utilizar los nombres de los

(2)

50

Cambiar las columnas que ocupan las variables

En otras ocasiones se desea cambiar la columna que ocupa una o múltiples variables dentro de una base de datos. Por ejemplo las medidas repetidas de un experimento deben estar obligatoriamente en columnas consecutivas. Si deseamos mover o trasladar la posición es tan simple como utilizar la función c( ) con el nuevo número que deseamos para las variables

en la base de datos. Supongamos que queremos ubicar en OBrienKaiser las 15 medidas

repetidas primero y por último los factores de treatment y gender.

OBrienKaiser = OBrienKaiser[ ,c(3:17,1,2)]

Recuerda del capítulo 1 que la forma de acceder a cualquier registro (fila) o variable (columna) de una base de datos se realiza mediante el uso de corchetes donde a la izquierda de la coma se definen las filas (si esta vació significa todas las filas) y a la derecha las columnas o variables. En este ejemplo hacemos que las primeras 15 variables sean las que actualmente ocupan las columnas 3 a la 17 y las últimas sean precisamente las dos primeras actuales. Asignamos ese reordenamiento al mismo objeto OBrienKaiser. Obviamente

podíamos haberlo asignado a cualquier otro objeto si quisiéramos conservar el original sin modificación alguna de su estructura interna.

Ordenar una base de datos por una o múltiples variables

La función ordena.por.variable.fnc( ) te permitirá ordenar una base de datos por una

determinada variable o variables en sentido ascendente (por defecto).

datos = ordena.por.variable.fnc(OBrienKaiser,

variables=c('treatment','gender','pre.1'))

--- *** Se ha ordenado (ascendente) la base de datos por las siguientes

*** variables: treatment gender pre.1 ---

Como hemos definido tres variables para ordenar la base de datos, primero se ordenarán por grupos de treatment dentro de este por gender y dentro de esta última por la variable pre.1. Si deseamos un orden descendente debemos incluir el argumento descedente=T.

datos = ordena.por.variable.fnc(OBrienKaiser, descendente=T, variables=c('treatment','gender','pre.1'))

--- *** Se ha ordenado (descendente) la base de datos por las siguientes

(3)

51

Operadores lógicos

La creación y filtraje de variables en una base de datos requiere con frecuencia de la inclusión de reglas o condiciones a aplicar a las variables a filtrar y este proceso se realiza mediante el uso de los de algún o algunos de los siguientes operadores lógicos.

== igual != diferente

< menor > mayor

<= menor o igual >= mayor o igual

& y | o ! negación

T verdadero F falso

Veamos algunos ejemplos de uso combinado de estos operadores lógicos para llevar a cabo labores de filtrado o establecimiento de condiciones sobre distintas variables.

sexo == 'hombre' & zona != 'centro'

Este filtraje adecuadamente incluido en la función subset( ) que veremos en el siguiente

apartado, selecciona los registros que sean hombres y cuya zona sea diferente centro. El

operador de igualdad como puedes ver es el doble signo igual (==) y no el signo igual simple (=) que como sabemos implica asignar y no comparar como es el caso del operador que nos ocupa.

(sexo == 'mujer' & edad >= 80) | (sexo == 'hombre' & edad >= 75)

Filtra si son mujeres y mayores o iguales a 80 años o (|) son hombres y mayores o iguales a 75

enfermo = T; empleado = F

Creamos dos variables lógicas (solo admiten verdadero (T) o falso (F) ): enfermo cuyo valor

es verdadero y empleado que es falso.

de.A = almacen$grupo == 'A'

Estamos creando un objeto lógico (tendrá solo dos valores posibles: verdadero o falso) de nombre de.A que resulta de comparar la variable grupo del objeto almacen con el valor A.

La variable generada de.A tendrá como valor verdadero (TRUE) si el sujeto pertenece al

grupo A y será falso (FALSE) si pertenece a cualquier otro que no sea A. Como de.A es un

(4)

52 ¿Qué registros (filas) de datos son del grupo A:

son.A = datos[de.A,]

En el objeto son.A solo habrá registros del almacén datos cuyo valor sea verdadero (T) en

el índice de.A calculado.

¿Qué registros de datos NO son del grupo A:

no.son.A = datos[!de.A, ]

Fíjate que usamos el operador lógico de negación (!). Por lo tanto en la nueva base de datos

no.son.A solo habrá registros (filas) de datos que tengan un valor falso (F) en el objeto de.A.

Supongamos que queremos crear un índice lógico (T o F) sobre OBrienKaiser que

seleccione a aquellos sujetos que pertenezcan al grupo control, que sean mujeres y cuyo

valor en la variable pre.2 esté por debajo de su media (mean(OK$pre.2)= 4.19).

OK=OBrienKaiser

indice= OK$treatment == 'control' & OK$gender == 'F' & OK$pre.2 <= mean(OK$pre.2)

indice

[1] FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

sum(indice) [1] 2

Los registros 3º y 4º cumplen con la condición. Podemos ahora utilizar el objeto lógico creado para extraer de la base de datos aquellos registros que cumplen con la condición o mediante el uso del operador lógico de negación (!) delante del vector los que no la cumplen.

OK[indice,] #Veríamos los dos registros que cumplen la condición

OK[!indice,] #Veríamos los registros que no cumplen la condición

Filtrar bases de datos mediante subset( )

Ya en el capítulo 1 tuvimos la oportunidad en el apartado de Funciones y argumentos de utilizar la función nativa de R subset( ). Con ella podemos llevar a cabo la selección de

aquellos registros de una base de datos que cumplan con ciertas condiciones impuestas por el usuario combinando adecuadamente los operadores lógicos del apartado anterior. Sobre la conocida data.frameOBrienKaiser podríamos aplicar los siguientes criterios de filtraje.

(5)

53

gr.1 = subset(OBrienKaiser,

treatment == 'control' & pre.3 > 4 )

Guardamos en el objeto gr.1 aquellos registros de la base de datos OBrienKaiser que

pertenezcan al grupo control y (&) que su valor en la variable pre.3 sea superior a 4.

gr.2 = subset(OBrienKaiser,

treatment != 'control' | pre.3 <= 3 )

Asignamos a gr.2 los registros diferentes (!=) al grupocontrol o (|) cuyo valor en la

variable pre.3sea menor o igual a 3.

gr.3 = subset(OBrienKaiser,

(treatment != 'control' & pre.3 <= 3) | (treatment == 'A' & pre.1 > 5) )

Guardamos engr.3los registros cuyo tratamiento sea distinto al grupocontrol y el valor

de pre.3menor o igual a 3 o el nivel de tratamiento seaA y el valor de pre.1mayor de 5.

Supongamos ahora la existencia de una base de datos ficticia de nombre integracion con

niños autóctonos e inmigrantes controlados con la variable origen. En la variable ingresos

tenemos algunos niños inmigrantes con superiores a los 2500€ y que constituyen según vemos en un diagrama de cajas unos casos extremos claros y deseamos por tanto que esos registros no participen en la investigación en curso.

seleccion = subset(integracion, origen == 'autoctono' |

(origen == 'inmigrante' & ingreso < 2500) )

Ahora el objeto seleccion tiene a los mismos niños de la base de datos integracion

salvo a los niños inmigrantes cuyos ingresos sean superiores a los 2500€. El filtro que hemos aplicado en el subset deja en primer término pasar a todos los niños cuyo origen sea autoctono o a los inmigrantes sólo si su nivel de ingreso es menor de 2.500€.

Filtrar bases de datos mediante el operador %in%

El operador %in% es de una gran utilidad cuando queremos por ejemplo seleccionar de una

base de datos aquellos registros que están o no en otra. Veamos un ejemplo:

Sobre la conocida base de datos iris que contiene 150 registros de 150 plantas, crearemos

una variable de nombre precisamente planta con el fin de identificar inequívocamente a

cada registro.

(6)

54

Ahora extraeremos una muestra aleatoria de iris de 75 observaciones utilizando la función

extrae.muestra.fnc que requiere como argumentos el tamaño de la muestra (n) que

deseamos así como la variable que actúa como unidad de registro y por lo tanto define que es un caso (ID). De esta forma extraerá 75 filas (plantas) aleatorias de las 150 posibles.

muestra = extrae.muestra.fnc(iris, n=75, ID='planta')

Ahora queremos seleccionar a los registros de iris que no han participado en la muestra

anterior. Para ello crearemos en primer lugar una variable lógica (solo tendrá dos valores: verdadero o falso) que llamaremos arbitrariamente indice utilizando precisamente el

operador %in%de la siguiente forma:

indice = iris$planta %in% muestra$planta

Aquí solicitas que indique con verdadero (T) o falso (F) y lo guarde en el vector indice,

aquellos casos de la variable planta de iris que se encuentran en la variable planta del

objeto muestra.

head(indice)

[1] TRUE FALSE FALSE FALSE FALSE TRUE

El registro (caso) 1 y 6 de iris está en la muestra aleatoria extraída. Ahora puedo utilizar la

variable lógica generada indice para seleccionar de iris aquellas plantas de las 150 que

forman parte de la muestra de esta manera:

iris[indice,]

o aquellos que NO forman parte de dicha muestra y que guardamos en resto de esta otra:

resto = iris[!indice,]

Observa que con el caracter ! decimos negación de indice, o lo que es lo mismo si un

registro es verdadero en indice y por lo tanto forma parte de la muestra, cuando le ponemos

delante dicho caracter el valor de indice será falso.

head(!indice)

[1] FALSE TRUE TRUE TRUE TRUE FALSE

head(indice)

[1] TRUE FALSE FALSE FALSE FALSE TRUE

Justamente los casos 1 y 6 aparecen ahora como falsos, y por lo tanto al incluir !indice

provoco justamente que esos dos casos (y todos los que sean FALSE) no entren a formar parte de la nueva base de datos resto, dado que como es obvio pertenecen al objeto

(7)

55

Reordenar los niveles de un factor

La función reordena.factor.fnc( ) te permitirá cambiar el orden de los niveles de un

factor desde su ordenamiento por defecto de carácter alfabético a un nuevo orden definido por el usuario. Otra de las opciones de gran utilidad de esta función esta en eliminar (haciendo

NA) aquellos niveles de un factor que el usuario desee. Asimismo permite cambiar la clase de

pertenencia de una variable (numérica, entera o carácter) a la clase factor.

El concepto de factor en R y específicamente en ULLRToolbox es de gran importancia. Para

ejemplificarlo vamos a utilizar la misma base de datos con la que venimos trabajando en este capítulo OBrienKaiser. La filtraremos seleccionando solo aquellos registros que no

pertenezcan a la condición control del factor treatment.

seleccion = subset(OBrienKaiser, treatment != 'control')

Ubicamos en seleccion todos los registros cuyo valor en la variable sea diferente del valor control. Observa que ocurre cuando pedimos la distribución de frecuencias de la variable

(factor) treatment:

frecuencias.fnc(seleccion, variable= 'treatment')

$treatment$tabla

control A B 0 4 7

El nivel control de la variable continua apareciendo aunque con cero registros en todas y

cada una de las funciones en las que la incluyamos. Evidentemente esto generará tanto problemas de orden estético (gráficas y tablas donde aparecerá el nivel control vacío) como

problemas de carácter numérico causado por celdilla vacía. La solución a este problema está en eliminar dicho nivel de entre los niveles posibles de la variable treatment. Lo haremos

con la función reordena.factor.fnc que nos permitirá además como indicamos

anteriormente reordenar los niveles (por defecto es alfabético) de un factor.

seleccion = reordena.factor.fnc(seleccion, que.factor = 'treatment', niveles=c('A','B') )

#--- # REORDENANDO NIVELES DEL FACTOR #--- *** Error, el número de niveles introducidos no coinciden con *** el número de niveles actual de la variable.

Estos son los niveles reales de la variable [1] "control" "A" "B"

y estos son los que pretendes reordenar [1] "A" "B"

(8)

56

Como el número de niveles que pretendemos reordenar no es igual al número de niveles real de la variable, la función lo asume como error. Como en este caso lo que queremos no es modificar el orden de los niveles incluidos en el argumento niveles, sino eliminar el que no

se nombra (control) lo haremos incluyendo el argumento hacer.NA=T (da por valor

perdido todo nivel de la variable no definido en el argumento niveles).

seleccion = reordena.factor.fnc(seleccion, que.factor= 'treatment', niveles=c('A','B'), hacer.NA=T )

#--- # REORDENANDO NIVELES DEL FACTOR #--- $hacer.NA

[1] TRUE

$niveles.antiguos

[1] "control" "A" "B"

$niveles.nuevos [1] "A" "B"

*** Tabla de frecuencias con el nuevo orden:

A B 4 7

Ahora como puedes ver el nivel eliminado control ya no aparece por ejemplo en la tabla de

frecuencias de la variable.

Creación de Nuevas variables

En R podemos generar nuevas variables de muchas maneras. En general podemos clasificar dicha actividad en 6 subtipos para los cuales hemos creado funciones específicas o utilizaremos comandos directamente disponibles en R. La creación de nuevas variables en

ULLRToolbox pueden subdividirse en los siguientes apartados:

• Creación de variables de forma simple

• Discretizado de variables continuas

• Recodificación de variables

• Nueva variable por cumplimiento de condiciones en otras existentes.

• Variable por aplicación de función de resumen sobre otras (media, dt, suma)

(9)

57

Creación simple de variables

Este procedimiento pasa en general por definir una nueva variable para un almacen dado que resulte de la aplicación de alguna transformación simple de los datos existentes. Algunos ejemplos podrían ser:

datos$nueva.variable = abs(datos$variable)

datos$nueva.variable = log(datos$variable1*datos$variable2)

datos$sujeto = 1:500

En el primer caso, deseamos que una variable sea el valor absoluto de otra. En la segunda, el logaritmo del producto de otras dos y en la última como hemos visto en ejemplos anteriores una secuencia de números que permitan definir el registro o el sujeto de la base de datos.

Discretizado de una variable

Cuando disponemos de medidas cuantitativas de caracter numérica o entero, podemos generar nuevas variables que resulten de la creación de grupos a partir de cortes realizados sobre la variable original. La discretización de una variable numérica la haremos utilizando la función

discretiza.variable.fnc. Dichos cortes pueden ser percentílicos, ordinales, por criterio

definido por el usuario o por cortes equi-espaciados de la unidad de origen de la variable objetivo.

Cortes Percentílicos

Podemos hacer cortes percentílicos por cuartiles, por deciles y por los percentiles 33, 66 y 100. De esta forma si elegimos los cuartiles la nueva variable tendría cuatro valores posibles:

Q1 hasta Q4 donde si un sujeto tiene un valor igual a Q1 en la nueva variable discretizada

significa que su valor en la original es igual o inferior al percentil 25. El criterio de corte podría también ser por deciles (D1 hasta D10). Así si un sujeto obtiene un valor igual a D2

significa que en la variable original este es superior al percentil 10 (primer decil) o igual o inferior al percentil 20 (decil segundo). Crearemos unos datos artificiales con una variable de nombre X los cuales asumiremos procedentes de dos poblaciones diferentes: primero y segundo curso N(10,3) y N(15,2) respectivamente.

grupo1 = data.frame( X= mvrnorm(50, mu=10, Sigma=3)) grupo1$curso= 'primero'

grupo2 = data.frame( X= mvrnorm(50, mu=c(15), Sigma=2)) grupo2$curso= 'segundo'

(10)

58

head(datos)

X curso 1 11.077924 primero 2 8.476432 primero 3 11.270248 primero 4 10.622915 primero 5 13.614811 primero 6 6.071192 primero

Hemos unido ambas muestras extraídas de dos poblaciones diferentes con la función

fundir.objetos.fnc definida en el capítulo anterior. Discretizaremos inicialmente la

variable X en cortes percentílicos de cuatro cuartiles (ntiles=4).

datos = discretiza.variable.fnc(datos, variable='X', ntiles=4)

#--- # DISCRETIZADO DE VARIABLE CONTINUA #--- $resumen

Min. 1st Qu. Median Mean 3rd Qu. Max. 4.296 9.851 12.900 12.460 14.900 17.460

$metodo

[1] "Cortes Percentilicos"

$tabla.n

Q1 Q2 Q3 Q4 Freq. 25 25 25 25

$tabla.medias

Q1 Q2 Q3 Q4 Media 8.238961 11.30459 14.11973 16.18347

---*** Se ha creado la variable X.r discretizado de la variable X ---***

---

Como puedes ver se ha creado automáticamente una nueva variable de nombre X.r con

cuatro niveles (Q1 a Q4). La frecuencia absoluta de cada grupo formado puedes ver que es 25

como corresponde al hecho de dichos cortes son de superficie y por lo tanto esperamos un recuento por grupo similar y dado que son 100 observaciones, 25 por grupo. La última tabla te informa del valor medio de la variable original X en cada cuartil.

(11)

59

histograma.fnc(datos, vd='X', que.factor='curso', orden= c(1,2) )

percentiles.fnc(datos,variable='X', que.factor='curso')

#--- # PERCENTILES #---

*** Percentiles de la variable: X en cada nivel de: curso ***

P.0. P.25. P.50. P.75. P.100.

curso.primero 4.2963 8.7901 9.8014 11.3692 14.1512

curso.segundo 11.7974 14.1643 14.9149 16.2321 17.4561

El error resulta evidente. No podemos realizar los cortes percentílicos de forma indiferenciada para ambas poblaciones porque tal y como podemos ver en la tabla de percentiles un niño de primero con un valor de 11.4 estaría en el percentil 75 mientras que si fuese de segundo

estaría ubicado en el percentil 25. Necesitamos por tanto discretizar incluyendo el hecho diferencial de pertenecer a dos poblaciones diferentes controladas por la variable curso.

datos = discretiza.variable.fnc(datos, variable='X', ntiles =4, que.factor = 'curso')

---

*** Se ha creado la varible X.r discretizado percentilico de la variable:

*** X en cada nivel del factor curso

--- $variables

[1] "curso:X.r"

$tabla

(12)

60

datos[c(1:3,51:53),] # Extraemos las 6 filas definidas en el vector c( )

X curso X.r 1 11.077924 primero Q3 2 8.476432 primero Q1 3 11.270248 primero Q3 51 14.467806 segundo Q2 52 14.979481 segundo Q3 53 13.418302 segundo Q1

Hemos pedido los 3 primeros niños de primero y los 3 primeros de segundo para que podamos valorar el impacto que ha tenido sobre la nueva variable el considerar en el discretizado percentílico las dos poblaciones definidas en la variable curso. El niño 3 tiene

un valor de 11.2 en la variable que le sitúa en el tercer cuartil (Q3). Sin embargo el niño 53

con un valor de 13.4 puntos claramente “superior” a 11.2 está en el primer cuartil (Q1).

datos = discretiza.variable.fnc(datos, variable='X', ntiles=4, que.factor = 'curso', var.out = 'X.cuartiles')

Si omitimos el argumento var.out (nombre que queremos para la variable resultante) se

generará una con el mismo nombre que la original a la que se le añade la terminación .r

(recodificada).

El argumento ntiles puede adquirir 3 valores diferentes: 3 (P33, P66 y P100), 4 (Q1 hasta

Q4) y 10 (deciles desde D1 hasta D10).

Cortes definidos por el usuario

Otro criterio para discretizar podría ser por puntos de cortes definidos por el usuario de esta forma podemos crear cuatro grupos de nivel de la variable X utilizando los siguientes criterios de corte “guiados teóricamente”.

mis.cortes=c(0,5,15,25)

mis.etiquetas=c('(<=5)', '(>5 <=15)', '(>15 <=25)')

El vector de cortes tiene cuatro elementos pero el de etiquetas tiene 3, la razón es que la función crea los cortes de la siguiente forma. Hará el primero para valores entre 0 y 5, el segundo para los superiores a 5 e igual o inferiores a 15 y el último grupo lo formarán las puntuaciones superiores a 15 e iguales o menores a 25. Hay por tanto 3 grupos para cuatro puntos de corte. Si omites el argumento etiquetas se crearan en este ejemplo tres niveles

con valores 1, 2 y 3.

datos = discretiza.variable.fnc(datos, variable='X',

(13)

61 $metodo

[1] "Cortes definidos por el usuario"

$tabla.n

(<=5) (>5 <=15) (>15 <=25) Freq. 2 75 23 $tabla.medias

(<=5) (>5 <=15) (>15 <=25) Media 4.506421 11.4999 16.28972

--- *** Se ha creado la variable X.cortes discretizado de la variable X *** ---

head(datos)

X curso X.r X.cortes

1 11.077924 primero Q3 (>5 <=15) 2 8.476432 primero Q1 (>5 <=15) 3 11.270248 primero Q3 (>5 <=15) 4 10.622915 primero Q3 (>5 <=15) 5 13.614811 primero Q4 (>5 <=15) 6 6.071192 primero Q1 (>5 <=15)

Dado que los cortes han sido definidos a priori, evidentemente el número de observaciones por nivel de la nueva variable no va a ser en absoluto equilibrado como ocurría con los cortes percentílicos.

Cortes equi-espaciados

El investigador podía desear que los grupos discretizados se crearan por cortes equiespaciados de la unidad de medida de la variable objetivo. Cuando este sea el caso el argumento cortes

tendrá solo un valor numérico indicando es número de grupos equi-espaciados que se desean.

datos = discretiza.variable.fnc(datos, variable='X', cortes = 3, var.out= 'X.espaciada')

$X.espaciada

1 2 3 media 7.072 10.593 15.197 dt 1.545 1.318 1.181 n 11.000 40.000 49.000

--- *** Se ha creado la variable X.espaciada, discretizado por

*** categorías de la variable X

---

(14)

62

diagrama.cajas.fnc(datos, vd = 'X', que.factor = 'X.espaciada')

Discretizado ordinal ascendente o descendente

La misma función puede utilizarse para crear una nueva variable que sea la versión ordinal ascendente o descendente de otra objetivo. Simplemente debemos incluir el argumento

ordinal=T. Por defecto se lleva a cabo de forma descendente (el valor mayor será el

primero en la nueva variable) aunque si se utiliza el argumento descendente=T el mayor

valor será el primero.

datos = discretiza.variable.fnc(datos, variable='X', ordinal=T)

*** Se ha creado la variable: X.ord discretizado ordinal de la *** *** variable: X

head(datos)

X curso X.ord 1 11.303242 primero 58 2 13.518584 primero 41 3 10.074044 primero 70 4 8.362101 primero 87 5 8.331394 primero 89 6 8.174565 primero 91

(15)

63

Recodificación de variables.

En la base de datos OBrienKaiser deseamos modificar los valores de la variable gender

desde los originales de Fpara mujer y Mpara hombre (iniciales en ingles) a los nuevos valores

mujer y hombre. Lo haremos con la función de la librería car (activada por defecto en el

toolbox) recode( ). Observa que en su nombre no lleva la extensión característica de ULLRToolbox.fnc. Es decir la forma en que trabaja es diferente al patrón visto hasta ahora

donde hay un primer argumento que es la base de datos a trabajar y la asignación de la salida a la misma base de datos o a otra si se desea tener una nueva. Ahora la salida es una variable concreta, la variable que se recodifica y no el almacén completo como hemos visto hasta ahora.

OBrienKaiser$genero = recode(OBrienKaiser$gender, "

'M'='hombre'; 'F'='mujer'; else=NA " )

La recodificación que hemos realizado con el comando recode sigue las siguientes reglas:

1. El resultado de la recodificación se asigna a una variable que se indica precedida con el nombre de la base de datos de pertenencia y el signo $: OBrienKaiser$genero

2. La recodificación se abre y se cierra obligatoriamente con el caracter comillas (“) 3. El primer argumento de la llamada será la variable que deseamos recodificar precedida

del nombre de la base de datos y el símbolo $: OBrienKaiser$gender

4. Cada una de las recodificaciones que se deseen para la variable objetivo deberán estar separadas entre sí por el caracter punto y coma (;): 'M'='hombre'; 'F'='mujer'

5. El subcomando else (opcional) permite asignar el resto de los valores posibles no

recogidos en las recodificaciones anteriores a otro valor o valor perdido (else=NA).

El proceso de recodificar variables cuando estas tienen muchos valores o niveles en el caso de que se trate de un factor puede ser muy tedioso y con una alta probabilidad de error. Seguidamente leeremos el archivo electrodos.txt que contiene los nombres de 27

electrodos que se ubican en la cabeza del sujeto en las investigaciones de potenciales evocados a eventos (ERP) siguiendo una distribución topográfica relativa a los distintos lóbulos (parietal, frontal, temporal, etc.).

electrodos = lee.archivo.fnc('electrodos.txt', hay.nombres = T, separador='tab')

(16)

64

head(electrodos)

numero electrodo 1 1 Fz 2 2 Cz 3 3 Pz 4 4 FC2 5 5 CP2 6 6 Fp2

Tenemos 27 canales y queremos crear una nueva variable de nombre hemisferio resultante

de la recodificación de electrodo agrupándolos precisamente según su ubicación en el

hemisferio izquierdo o derecho. La forma óptima de realizar esta recodificación con tantos niveles, sería crear primero dos vectores de nombre izquierdo y derecho cada uno

conteniendo aquellos electrodos que se ubican precisamente en cada hemisferio.

izquierdo = c('F7','F3','FC5','FC1','T7','C3','CP5','CP1','P7','P3')

derecho = c('F8','F4','FC2','FC6','T8','C4','CP2','CP6','P8','P4')

Una vez definidos los vectores podemos proceder a la recodificación de una forma muy simple y rápida.

electrodos$hemisferio = recode(electrodos$electrodo, " izquierdo = 'izquierdo'; derecho = 'derecho'; else=NA ")

La nueva variable hemisferio, tendrá la etiqueta 'izquierdo' (observa los apóstrofes en

el lado derecho de la recodificación) si el electrodo es alguno de los que se encuentran dentro del vector izquierdo. La etiqueta 'derecho' se asignará en la nueva variable hemisferio a cualquier electrodo incluido en el vector creado anteriormente con el nombre

derecho. Dado que quedan electrodos sin ubicar (7) decidimos que estos sean considerados

como valor perdido en la nueva variable creada, mediante la inclusión de else=NA.

head(electrodos)

numero electrodo hemisferio 1 1 Fz <NA> 2 2 Cz <NA> 3 3 Pz <NA> 4 4 FC2 derecho

5 5 CP2 derecho

6 6 Fp2 <NA>

Como los electros Fz, Cz, Pz y FP2 ( y 3 mas no incluidos en la cabecera) no estaban en los

vectores creados anteriormente aparecen en la nueva variable como perdidos por el sistema

(<NA> para variables no numéricas). Como FC2 y CP2 estaban en el vector derecho en la

(17)

65

Una utilidad importantísima y de gran uso del recode estaría en la posibilidad de hacer

valores perdidos a aquellos de una variable que cumplan un determinado criterio.

datos$tr = recode(datos$tr, " lo:200 = NA; 4000:hi =NA ")

Todo valor de la variable tr (tiempo de reacción) menor o igual a 200 ms será perdido por

el sistema (NA) al igual que todos los valores iguales o superiores a 4000 ms. Los valores

utilizados lo y hi se refieren a low y hig, menor y mayor respectivamente en ingles.

Recodificación de múltiples variables con el mismo criterio.

En muchas ocasiones sobre todo con cuestionarios, es muy común la existencia de items que se han invertido para evitar la deseabilidad social del sujeto que responde. En estas circunstancias, lo normal es reinvertir los valores de la variable para que todos los items pertenecientes a una misma escala presenten el mismo "sentido". La forma más rápida y eficiente de lograrlo es con la función creada a tal efecto recode.multiple.fnc (P.Prieto y Juan A. Hernández) que lleva a cabo precisamente esta labor.

Utilizaremos como ejemplo la base de datos bfi (2800 sujetos) de la librería psych perteneciente al cuestionario autoadministrado Synthetic Aperture Personality Assessment (SAPA) con 25 items en 5 escalas: Conformidad, Autoconsciencia, Extraversión, Neuroticismo y Apertura. En dichas escalas, los items 1,9,11,12,22 y 25 están invertidos. Veamos el procedimiento de reinvertirlos al mismo sentido que el resto de los items.

bfi= recode.multiple.fnc(bfi, variables=c(1,9,11,12,22,25),

valor1=1:6, valor2=6:1)

#---

# RECODIFICACION MULTIPLE DE VARIABLES

#---

*** Se han recodificado las siguientes variables:

[1] "A1" "C4" "E1" "E2" "O2" "O5"

*** desde los valores originales: 1 2 3 4 5 6

*** a los nuevos: 6 5 4 3 2 1

Observa que hemos incluido dos argumentos nuevos: valor1 y valor2 relativos a los valores originales y a los nuevos a recodificar.

Si desear conservar las variables originales y por lo tanto recodificar en variable diferente debes incluir el argumento nueva.variable=T.

bfi= recode.multiple.fnc(bfi,

(18)

66

#--- # RECODIFICACION MULTIPLE DE VARIABLES #---

*** Se han recodificado las siguientes variables: [1] "A1" "C4" "E1" "E2" "O2" "O5"

*** En estas nuevas variables:

[1] "A1.r" "C4.r" "E1.r" "E2.r" "O2.r" "O5.r"

*** desde los valores originales: 1 2 3 4 5 6

*** a los nuevos: 6 5 4 3 2 1

Si las nuevas variables a crear ya existiesen en la base de datos (por una recodificación anterior) la función te dará el siguiente mensaje de error, indicándote que debes o renombrar la o las variables de la base de datos o incluir el argumento sustituye=T para sustituir las antiguas variables por las nuevas.

#--- # RECODIFICACION MULTIPLE DE VARIABLES #---

*** Error. Parece que esas variables han sido anteriormente recodificadas, *** puesto que ya existen en la base de datos. Estas son esas variables: [1] "A1.r" "C4.r" "E1.r" "E2.r" "O2.r" "O5.r"

*** Renombralas si deseas conservarlas con cambia.nombre.var.fnc *** o incluye el argumento sustituye=T en la llamada a la función.

bfi= recode.multiple.fnc(bfi,

variables=c(1,9,11,12,22,25), valor1=1:6, valor2=6:1, nueva.variable=T, sustituye=T)

Nueva variable por cumplimiento de criterios en otras existentes

Es muy común que la creación de una nueva variable se haga de tal forma que sus diferentes niveles o valores lo sean según se cumplan o no determinadas condiciones a través de múltiples variables incluidas en el sistema. Veamos el proceso con la base de datos

OBrienKaiser. Queremos crear la variable cualitativa bloque.1 que tendrá dos niveles:

bajo si el sujeto pertenece al grupo de tratamiento control y su valor en la variable fup.1

es menor de 8. El nivel alto será para cualquier otro registro que no cumpla la condición

(19)

67

OK=OBrienKaiser

Para hacer más manejable la base de datos hemos hecho una copia en OK (es más corto).

OK$bloque.1='alto'

OK$bloque.1[OK$treatment=='control' & OK$fup.1 < 8] ='bajo'

De entrada creamos la variable bloque.1 siguiendo el procedimiento de creación simple de

variable visto anteriormente. Observa que hemos asignado como valor “único” alto. Si pides

un head de OK en ese momento verás que todos los registros tienen ese mismo valor. En la

siguiente línea hacemos que todos los registros que pertenezcan al grupo control de tratamiento y (&) que además tengan un valor inferior a 8 en la variable fup.1 tengan la

etiqueta (nivel) alto en la nueva variable bloque.1.

El formato genérico de la instrucción anterior obedece al siguiente esquema:

almacen$nueva.variable[condiciones] = nuevo.valor

Veamos finalmente la distribución de frecuencias de la nueva variable creada bloque.1.

frecuencias.fnc(OK, variable='bloque.1')

#--- # TABLA DE FRECUENCIAS #---

$bloque.1

$bloque.1$n.total [1] 16

$bloque.1$tabla

alto bajo 11 5

Los errores más frecuente en esta modalidad de creación de variables son fundamentalmente:

1. Omitir el nombre genérico del almacén más los corchetes como contenedor de las condiciones a aplicar.

OK

$bloque.1

[

OK$treatment=='control' & OK$fup.1 < 8] ='bajo'

2. Omitir el nombre del almacén (OK en este ejemplo) más el signo $ delante de cada

variable de las condiciones.

OK$bloque.1[OK$treatment=='control' & OK$fup.1 < 8]='bajo'

3. Omitir el conjunto $nombre.de.la.nueva.variable y el nuevo valor al final de

la condición que debe cumplirse.

(20)

68

Creación de variable por aplicación de función de resumen sobre otras

Si aplicamos un cuestionario a 100 sujetos que consta de 50 preguntas correspondientes a 5 sub-escalas cuyo resultado es 1 o 0 según los sujetos acierten o no cada pregunta obtendremos una matriz de 100 x 50 sobre la cual desearemos tener 5 nuevas variables con la suma o la media de los aciertos para cada uno de las 5 escalas (10 preguntas por escala). Para obtener estas nuevas variables que resultan de aplicar una función de resumen con los estadísticos de media, mediana o suma utilizaremos la función compute.fnc. Crearemos en primer lugar

una base datos ficticia (simulada con R) con estas características.

datos = data.frame(abs(round(mvrnorm(100, mu=rep(0,50), Sigma=diag(1,50)),0)))

for(i in 1:50) datos[,i] = recode(datos[,i], " 2:hi=1 ")

Recodificamos con el bucle for cada una de las 50 variables haciendo que todo valor igual o

superior a 2 sea 1. De esa manera provocamos que todas las variables sean por tanto

dicotómicas (1 y 0).

head(datos)

X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 1 0 0 1 1 1 1 1 1 0 1 0 0 0 0 1 1 0 0 1 0 2 0 1 0 1 0 0 1 0 0 0 0 1 1 0 1 1 1 1 0 0 3 1 1 1 1 1 1 0 1 0 1 0 0 0 0 0 1 0 1 1 1 4 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 1 1 1 0 5 1 0 1 0 1 0 0 1 1 1 1 0 1 1 1 0 1 1 1 0 6 0 1 1 0 1 0 1 1 1 1 1 1 1 0 1 1 1 0 0 1

Omitimos de la cabecera anterior las 30 variables restantes por motivos de espacio. Puedes comprobar que todas adoptan solo dos valores posibles: 0 y 1 según el sujeto haya acertado o

no la pregunta del cuestionario.

Ahora queremos crear 5 nuevas variables que resultan de la media de aciertos para cada una de las 5 escalas con 10 ítems o preguntas cada una de ellas. Lo primero que debemos hacer es crear una lista donde definiremos que nombre queremos para cara nueva variable y las columnas (o nombres) de las variables sobre las que queremos aplicar la función de resumen (por defecto la media).

mi.lista = list(E1=1:10, E2=11:20, E3=21:30, E4=31:40, E5=41:50)

mi.lista

$E1

[1] 1 2 3 4 5 6 7 8 9 10

$E2

[1] 11 12 13 14 15 16 17 18 19 20

$E3

(21)

69 $E4

[1] 31 32 33 34 35 36 37 38 39 40

$E5

[1] 41 42 43 44 45 46 47 48 49 50

Como las columnas de las variables a incluir son consecutivas en la base de datos no necesitamos utilizar el comando c( ) simplemente indicamos el principio y fin de las

columnas separadas por el caracter dos puntos. Una vez definida la lista con los nombres de las nuevas variables y las columnas sobre las que aplicar la función de resumen (media, mediana, suma o sc relativo a sumas de cuadrados), podemos llamar a la función

compute.fnc( ).

datos = compute.fnc(datos, variables = mi.lista)

*** Se han creado las nuevas variables E1 E2 E3 E4 E5 aplicando la *** funcion de resumen media

head(datos[,51:55])

E1 E2 E3 E4 E5 1 0.7 0.3 0.6 0.8 0.6 2 0.3 0.6 0.8 0.7 0.6 3 0.8 0.4 0.4 0.6 0.7 4 0.6 0.6 0.7 0.7 0.8 5 0.6 0.7 0.5 0.9 0.7

Por defecto el argumento estadistico es la media, otras funciones de resumen serían la

suma, mediana o sc (sumas de cuadrados).

datos = compute.fnc(datos, variables = mi.lista, estadistico='suma')

head(datos[,51:55])

E1 E2 E3 E4 E5 1 7 3 6 8 6 2 3 6 8 7 6 3 8 4 4 6 7 4 6 6 7 7 8 5 6 7 5 9 7 6 7 7 8 4 8

(22)

70

Variable de recuento

Crea una nueva variable que resulta de la frecuencia absoluta (recuento) del cumplimiento de un determinado valor o valores definidos por el usuario en p variables ya sean estos valores numéricos como alfanuméricos mediante la función recuento.fnc( ).

Partiremos de una base de datos simulada en la que recrearemos las respuestas de 50 sujetos en 5 variables con cinco alternativas. Deseamos generar una nueva variable que resulte del recuento de la presencia de los valores 0 y 1 para cada sujeto.

Generamos los datos artificiales mediante las siguientes líneas. Cópialas, pégalas y ejecútalas en tu script para generar una muestra aleatoria (tus resultados serán ligeramente diferentes) de dichos datos.

datos = data.frame(abs(round(mvrnorm(100, mu=rep(1,5), Sigma= diag(1,5)),0)))

head(datos)

X1 X2 X3 X4 X5 1 1 0 2 1 2 2 0 0 3 1 0 3 1 0 0 0 1 4 1 1 1 1 2 5 2 1 0 3 1 6 0 1 2 0 0

datos= recuento.fnc(datos, variables=1:5, criterio= c(0,1), new.var='recuento')

O de forma similar dado que la base de datos está compuesta exclusivamente por las variables sobre las que de desea realizar el recuento. Si no incluyes el argumento variables se

utilizarán todas las existentes y si omites el argumento new.var, se creará por defecto una

nueva variable de nombre recuento.

datos= recuento.fnc(datos, criterio=c(0,1))

#--- # Recuento de variables #---

*** Se ha creado con exito la variable de recuento: recuento

head(datos)

(23)

71

El primer sujeto tiene un valor de 3 en la variable recuento porque verifica la condición 0 o 1

en 3 (X1, X2 y X4) de las 5 variables a rastrear.

Imaginemos ahora que en las variables poseen muchos más valores y que deseamos un límite que resulta imposible de definir mediante el criterio anterior (el argumento criterio debería entonces incluir un gran número de valores o un condicional no permitido como <= 100, etc.). La solución pasa por discretizar previamente dichas variables definiendo un vector de cortes y etiquetas como hemos visto en apartados anteriores, para posteriormente solicitar el recuento sobre las nuevas variables generadas. Veamos el procedimiento con la base de datos

OBrienKaiser. Queremos realizar un recuento sobre las 15 variables de medidas repetidas

(pre.1 hasta fup.5) que tengan un valor igual o inferior a 2.

1. Definiremos en primer lugar el vector de cortes que deseamos para los datos y sus etiquetas correspondientes.

cortes = c(0,2,5,16); etiquetas = c(1,2,3)

OK = OBrienKaiser # Acortamos el nombre demasiado largo

Tenemos 4 valores en el vector de cortes y 3 etiquetas. Así todo valor entre 0 y 2 tendrá en la nueva variable discretizada el valor 1. Todo valor superior a 2 y hasta 5 el nuevo valor 2 y

cualquier valor mayor que 5 y menor o igual a 16 un 3. Observa, como siempre el vector de

etiquetas ha de tener un valor menos que su correspondiente vector de cortes.

2. Crearemos seguidamente un bucle for que nos permitirá recodificar las 15 variables de

forma automática. Observa el argumento variable que tiene como valori. Es decir i se

irá modificando desde su valor de inicio 3 hasta el último de 17. Y por tanto se va

discretizando de forma automática una a una hasta completar el bucle.

for(i in 3:17)

OK = discretiza.variable.fnc(OK, variable=i,

cortes=cortes, etiquetas=etiquetas)

Con variables=i hacemos que el bucle for vaya modificando de forma automática cada

variable desde la 3 hasta la 17. Con nombres.var(OK) accedemos al nombre, columna y

tipo de las variables de las nuevas variables generadas en la data.frame.

nombres.var(OK)

nombre numero tipo 1 treatment 1 factor .

18 pre.1.r 18 numeric .

23 post.1.r 23 numeric .

27 post.5.r 27 numeric 28 fup.1.r 28 numeric .

(24)

72

head(OK[,c(3,4,18,19)]) # Veamos las dos primeras y su versión discretizada

pre.1 pre.2 pre.1.r pre.2.r

1 1 2 1 1 2 4 4 2 2 3 5 6 2 3 4 5 4 2 2 5 3 4 2 2

Podemos ver las nuevas variables generadas (.r sufijo que se añade por defecto cuando se discretiza una variable) que ocupan las columnas 18 a la 32.

3. Estamos preparados para solicitar el recuento de nuestras nuevas variables utilizando el argumento criterio=1 en la llamada a la función, dado que en la nueva variable serán 1

todos los registros que en la original tengan un valor entre 0 y 2.

Podemos ya realizar el recuento con las nuevas variables discretizadas (18 a la 32) utilizando

como criterio el valor 1.

OK = recuento.fnc(OK, variables=18:32, criterio =1)

#--- # Recuento de variables #---

*** Se ha creado con exito la variable de recuento: recuento ***

head(OK[,30:33])

fup.3.r fup.4.r fup.5.r recuento

1 1 1 2 13 2 3 1 1 8 3 3 2 3 2 4 2 1 2 6 5 3 1 2 2 6 3 2 3 0

Si repitiéramos el proceso de discretizar pero esta vez no por cortes definidos por el usuario sino aplicando un criterio de cuartiles (ntiles=4). Obtendríamos las mismas variables en

versión cualitativa con valores entre Q1 y Q4. De esta forma podríamos plantear una nueva

variable de recuento que recogiese el número de observaciones menor o igual al primer cuartil (criterio='Q1') o con los sujetos mayor o igual al 3 cuartil: criterio=c('Q3', 'Q4')

for(i in 3:17)

OK = discretiza.variable.fnc(OK, variable=i, ntiles=4)

(25)

73

head(OK[,c(3,4,18,19,33)])

pre.1 pre.2 pre.1.r pre.2.r recuento

1 1 2 Q1 Q1 0 2 4 4 Q2 Q2 0 3 5 6 Q3 Q4 7 4 5 4 Q3 Q2 3 5 3 4 Q2 Q2 4 6 7 8 Q4 Q4 14

Ejercicios

1. Cambia los nombres de las variables 3ª, 4ª y 6ª de la base de datos attitude a los nuevos

nombres privilegios, aprendizaje y critico.

2. Reordena todas las variables de la base de datos attitude donde la variable rating sea la

última y privileges la primera.

3. Ordena de menor a mayor la base de datos attitude por la variable rating.

4. Selecciona y asigna de la base de datos attitude aquellos registros que tengan un valor de rating menor a 60 y cuyo valor de complaints sea mayor o igual a 40. Repite el

procedimiento permitiendo el pase del filtro si se cumple cualquiera de las dos condiciones. 5. Reordena los niveles del factor gender de la base de datos OBrienKaiser de tal manera

que el primer nivel sea M y el segundo F.

6. En la base de datos OBrienKaiser crea una variable de nombre sujeto con valores desde 1 hasta el número total de sujetos del objeto.

7. Crea una versión discreta percentílica por cuartiles de la variable rating de la base de datos

attitude.

8. Crea una variable de 4 cortes equiespaciados de la variable complaints de la base de datos

attitude. Describe la tabla de medias de complaints en cada nivel de la nueva variable

generada complaints.c.

9. Recodifica en la misma variable a valor perdido (NA) todos los valores de privileges de

la base de datos attitude menores o iguales a 40 y iguales o superiores a 80.

10. Crea una nueva variable en attitude con el nombre de filtro donde valga 1 si rating

es menor de 45 y complaints mayor de 60. Valor 2 si rating es mayor o igual a 50 y

complaints menor de 70. Todos los demás registros de las variables que no cumplan con

estas condiciones deben ser perdidos por el sistema (NA).

11. Sobre la base de datos iqitems crea dos variables de nombre F1 y F2 que serán la suma de

todas las puntuaciones incluidas en las dos escalas formadas por las variables de las columnas 1,5,10,2,8,3 para F1 y 9,11,7 para F2.

12. Crea en iqitems una variable de recuento que surja de la frecuencia absoluta de que los

Referencias

Documento similar

Tras establecer un programa de trabajo (en el que se fijaban pre- visiones para las reuniones que se pretendían celebrar los posteriores 10 de julio —actual papel de los

Por PEDRO A. EUROPEIZACIÓN DEL DERECHO PRIVADO. Re- laciones entre el Derecho privado y el ordenamiento comunitario. Ca- racterización del Derecho privado comunitario. A) Mecanismos

You may wish to take a note of your Organisation ID, which, in addition to the organisation name, can be used to search for an organisation you will need to affiliate with when you

Where possible, the EU IG and more specifically the data fields and associated business rules present in Chapter 2 –Data elements for the electronic submission of information

The 'On-boarding of users to Substance, Product, Organisation and Referentials (SPOR) data services' document must be considered the reference guidance, as this document includes the

Products Management Services (PMS) - Implementation of International Organization for Standardization (ISO) standards for the identification of medicinal products (IDMP) in

This section provides guidance with examples on encoding medicinal product packaging information, together with the relationship between Pack Size, Package Item (container)

Cedulario se inicia a mediados del siglo XVIL, por sus propias cédulas puede advertirse que no estaba totalmente conquistada la Nueva Gali- cia, ya que a fines del siglo xvn y en