[R-es] Crear datos aleatorios con restriciones

Carlos Ortega cof en qualityexcellence.es
Mar Jul 14 09:31:55 CEST 2015


OK.
Bueno, para esa última parte para tener un data.frame con toda la
información, ya filtrada y con los datos de los profesores puedes hacer
esto:

#------------------------------------------
#Si a los "validPairs" tengo que asignar "T" profesores
t <- 10
teachers <- data.frame(
                       Name=sample(paste("Prof_",1:t, sep=""),t)
                      ,Speciality=sample(paste("Spec_",1:t, sep=""),t)
                      ,Age=sample(25:60,t)
                      )

placesEnd <- validPairs[sample(1:nrow(validPairs), t), ]
row.names(placesEnd) <- NULL
placesEndRed <- placesEnd[,c(1,2,3,6)]
names(placesEndRed) <- c("School", "Grade", "Class_1", "Class_2")
endAssig <- cbind.data.frame(placesEndRed, teachers)
endAssig

#------------------------------------------

Que produce este tipo de resultado:

> endAssig
   School Grade Class_1 Class_2    Name Speciality Age
1     e11    g2      c3     c18  Prof_2     Spec_5  39
2     e11    g2      c5     c16  Prof_8     Spec_1  49
3     e12    g1      c3     c17  Prof_1    Spec_10  36
4      e2    g2     c15     c17 Prof_10     Spec_9  29
5      e1    g3      c9     c15  Prof_3     Spec_6  55
6      e6    g3      c2     c18  Prof_6     Spec_8  42
7     e17    g2      c9     c14  Prof_4     Spec_3  27
8     e18    g3      c2     c12  Prof_7     Spec_2  53
9     e13    g1     c10     c20  Prof_9     Spec_4  58
10    e18    g2      c4     c19  Prof_5     Spec_7  59

Saludos,
Carlos Ortega
www.qualityexcellence.es


El 14 de julio de 2015, 1:00, Ignacio Martinez <ignacio82 en gmail.com>
escribió:

> Perdon por no se lo suficientemente claro :(
>
> Tu codigo produce `validPairs` que tiene 7 variables y 360 observaciones.
> Donde
>
> > validPairs[1,]   V1 V2 V3 V4 V5 V6 valid
> 60 e1 g1 c1 e1 g1 c2 Valid
>
>
> indica que un maestro tiene asignado c1 y c2 en la escuela e1 y el grado
> g1. Correcto? Si es asi, esto es casi lo que queira producir y creo que
> puedo llegar a donde quiero usando tu codigo de base.
>
> El objecto que yo quiero generar es el que genero en stakoverflow
> `schoolGrade`. Donde
>
> > schoolGrade[1:2,]  grade   School.ID Classroom       Teacher.ID Teacher.exp Teacher.Other  Teacher.RE
> 1     3 Modi School         A    Sage, Kendell    27.87402             0 -0.04372723
> 2     4 Modi School         A Delgado, Vanessa    26.20701             0 -0.88280564
>
>
> Es decir, cada observación es un aula en una escuela con informacion sobre
> el grado, nombre del maestro, otras caracteristics del maestro.
>
> Muchas gracias por la ayuda.
>
>
>
> On Mon, Jul 13, 2015 at 6:37 PM Carlos Ortega <cof en qualityexcellence.es>
> wrote:
>
>> Hola,
>>
>> No entiendo muy bien.
>> El número de clases lo puedes modificar a tu gusto, en la variable
>> "numDi".
>>
>> He puesto un valor de ejemplo de 4 porque así aparecía en tu código,
>> obviamente puedes poner otro valor...
>> La única limitación aparecerá cuando escojas un valor muy grande y el
>> cálculo de las combinaciones posibles tarde en generarse. He probadoc con
>> 20 y sigue siendo manejable.
>>
>> #---------------------------------------------
>>
>> #Generar "c" Divisiones: c1, c2, c3...
>> *numDi <- 4*
>> divis <- paste("c", 1:numDi, sep="")
>> #----------------------------------------------
>>
>> Y la otra discrepancia parece ser el número de combinaciones válidas.
>> Lo que has dicho es que quieres "asignar un profesor a una escuela un
>> grado y dos clases". Dos clases, del mismo colegio y en el mismo grado, ¿es
>> así?...
>>
>> Saludos,
>> Carlos Ortega
>> www.qualityexcellence.es
>>
>>
>>
>> El 14 de julio de 2015, 0:07, Ignacio Martinez <ignacio82 en gmail.com>
>> escribió:
>>
>>> Gracias Carlos,
>>>
>>> Tu codigo es un gran paso en el sentido correcto pero no produce
>>> exactamente lo que estoy buscando.
>>>
>>> Mi "solucion" en stackoverflow
>>> <http://stackoverflow.com/questions/31137940/randomly-assign-teachers-to-classrooms-imposing-restrictions/31143808#31143808>
>>> produce un data frame `schoolGrade` con 240 observaciones y 7 variables. Mi
>>> objetivo es poder generar un data frame asi pero con la flexibilidad de
>>> poder usar n.classrooms <- 20 (o cualquier otro numero) en lugar de 4
>>> (hardcoded)
>>>
>>> Gracias de nuevo!
>>>
>>> Ignacio
>>>
>>>
>>>
>>>
>>> On Mon, Jul 13, 2015 at 5:54 PM Carlos Ortega <cof en qualityexcellence.es>
>>> wrote:
>>>
>>>> Hola,
>>>>
>>>> Esta es una forma de hacerlo, evitando bucles....
>>>>
>>>>
>>>> #------------------------------------------------------------------------------------------
>>>> #1. Quiero generar N escuelas, con G grados y C divisiones.
>>>> #2. Quiero asignar cada uno de T maestros a 2 divisiones en un grado y
>>>> escuela
>>>>
>>>> #---------------------- Combinaciones de: Escuelas - Grados - Divisiones
>>>> #Generar "n" Escuelas: e1, e2, e3...
>>>> numEs <- 20
>>>> escuelas <- paste("e", 1:numEs, sep="")
>>>>
>>>> #Generar "g" Grados: g1, g2, g3...
>>>> numGr <- 3
>>>> grados <- paste("g", 1:numGr, sep="")
>>>>
>>>> #Generar "c" Divisiones: c1, c2, c3...
>>>> numDi <- 4
>>>> divis <- paste("c", 1:numDi, sep="")
>>>>
>>>>
>>>> #Agrupo Escuelas - Grados
>>>> EsGra <- outer(escuelas, grados, FUN="paste")
>>>>
>>>> #Agrupo (Escuelas - Grados) - Divisiones
>>>> EsGraDiv <- outer(EsGra, divis, FUN="paste")
>>>>
>>>> #Estas son todas las combinaciones de Escuelas-Grados-Divisiones
>>>> EsGraDivTmp <- as.matrix(EsGraDiv, ncol=1, nrow=length(EsGraDiv) )
>>>> EsGraDivEnd <- as.data.frame(EsGraDivTmp)
>>>>
>>>> #---------------------- Profesores
>>>> #Asignar a cada uno de los T maestros a 2 clases en 1 grado y 1 escuela
>>>> #Al ser 2 clases creo todas las parejas posibles
>>>> #de las que escogeré 2 clases del mismo grado y misma escuela
>>>> Allpairs <- as.data.frame(t(combn(EsGraDivTmp, 2)))
>>>> AllpairsTmp <- paste(Allpairs$V1, Allpairs$V2, sep=" ")
>>>>
>>>> #Aqui tengo las parejas en la misma fila y separadas en columnas
>>>> library(stringr)
>>>> separoPairs <- as.data.frame(str_split_fixed(AllpairsTmp, " ", 6))
>>>>
>>>> #de este data.frame escojo filas donde V1=V4 y V2=V5 : misma escuela +
>>>> mismo grado
>>>> separoPairs$valid <- ifelse(separoPairs$V1 == separoPairs$V4 &
>>>> separoPairs$V2 == separoPairs$V5, "Valid", "Invalid")
>>>>
>>>> #Resultado Final
>>>> validPairs <- separoPairs[separoPairs$valid=="Valid",]
>>>>
>>>> #Si a los "validPairs" tengo que asignar "T" profesores, de forma
>>>> aleatoria
>>>> t <- 10
>>>> validPairs[sample(1:nrow(validPairs), t), ]
>>>>
>>>> #---------------------------------------------------------
>>>>
>>>> Saludos,
>>>> Carlos Ortega
>>>> www.qualityexcellence.es
>>>>
>>>>
>>>> El 13 de julio de 2015, 21:03, Ignacio Martinez <ignacio82 en gmail.com>
>>>> escribió:
>>>>
>>>>> Hola,
>>>>>
>>>>> 0. La falta de 'elegancia' hace que sea mas dificil hacer cambios al
>>>>> codigo. Por ejemplo cambiar n.classrooms <- 4 a n.classrooms <- 20
>>>>>
>>>>> 1. Cuando tengo solo 4 puedo hacer esto:
>>>>>
>>>>> schoolGrade$A <- Teachers$Teacher.ID[1:cuttoff1]
>>>>> schoolGrade$B <- Teachers$Teacher.ID[1:cuttoff1]
>>>>> schoolGrade$C <- Teachers$Teacher.ID[(cuttoff1+1):n.teachers]
>>>>> schoolGrade$D <- Teachers$Teacher.ID[(cuttoff1+1):n.teachers]
>>>>>
>>>>> Pero si tengo 20 tendria que escribir 20 lines en lugar de 4 y
>>>>> calcular los cutoff para cada linea. Con 20 classrooms por escuela y por
>>>>> grado tengo que asignar 600 maestros a 2 classrooms cada uno.
>>>>>
>>>>> 2. No necesito todas las asignaciones posible, con una es suficiente.
>>>>>
>>>>> Gracias!
>>>>>
>>>>> On Mon, Jul 13, 2015 at 2:54 PM Carlos Ortega <
>>>>> cof en qualityexcellence.es> wrote:
>>>>>
>>>>>> Hola,
>>>>>>
>>>>>> ¿Pero el problema que tienes es de "elegancia del código" como
>>>>>> indicas en StackOverflow?
>>>>>> o ¿de performance porque al subir el número de clases el número total
>>>>>> de combinaciones te explota?...
>>>>>>
>>>>>> En cuanto a las asignaciones de los profesores, ¿quieres tener todas
>>>>>> las posibles asignaciones? ¿un solo caso de asignación?...
>>>>>>
>>>>>> Saludos,
>>>>>> Carlos Ortega
>>>>>> www.qualityexcellence.es
>>>>>>
>>>>>> 2015-07-13 15:23 GMT+02:00 Ignacio Martinez <ignacio82 en gmail.com>:
>>>>>>
>>>>>>> Hola,
>>>>>>>
>>>>>>> Esta pregunta la hice en stackoverflow
>>>>>>>
>>>>>> <
>>>>>>> http://stackoverflow.com/questions/31137940/randomly-assign-teachers-to-classrooms-imposing-restrictions/31143808#31143808
>>>>>>> >pero
>>>>>>
>>>>>>
>>>>>>> nadie pudo contestarla.
>>>>>>>
>>>>>>> 1. Quiero generar N escuelas, con G grados y C divisiones.
>>>>>>> 2. Quiero asignar cada uno de T maestros a 2 divisiones en un grado y
>>>>>>> escuela
>>>>>>>
>>>>>>> Si tengo C=4 divisiones, puedo lograr lo que quiero con este código:
>>>>>>>
>>>>>>> library(randomNames)
>>>>>>> set.seed(6232015)
>>>>>>> n.schools <-20
>>>>>>> n.grades <- 3
>>>>>>> n.classrooms <- 4
>>>>>>> total.classrooms <- n.classrooms*n.grades*n.schools
>>>>>>>
>>>>>>> gen.names <- function(n, which.names = "both", name.order =
>>>>>>> "last.first"){
>>>>>>>   names <- unique(randomNames(n=n, which.names = which.names,
>>>>>>> name.order = name.order))
>>>>>>>   need <- n - length(names)
>>>>>>>   while(need>0){
>>>>>>>     names <- unique(c(randomNames(n=need, which.names = which.names,
>>>>>>> name.order = name.order), names))
>>>>>>>     need <- n - length(names)
>>>>>>>   }
>>>>>>>   return(names)}
>>>>>>> #Generates teachers data frame
>>>>>>> n.teachers=total.classrooms/2
>>>>>>> gen.teachers <- function(n.teachers){
>>>>>>>   Teacher.ID <- gen.names(n = n.teachers, name.order = "last.first")
>>>>>>>   Teacher.exp <- runif(n = n.teachers, min = 1, max = 30)
>>>>>>>   Teacher.Other <- sample(c(0,1), replace = T, prob = c(0.5, 0.5),
>>>>>>> size = n.teachers)
>>>>>>>   Teacher.RE <- rnorm(n = n.teachers, mean = 0, sd = 1)
>>>>>>>   Teachers <- data.frame(Teacher.ID, Teacher.exp, Teacher.Other,
>>>>>>> Teacher.RE) %>% mutate(Teacher.ID=as.character(Teacher.ID))
>>>>>>>   return(Teachers)}
>>>>>>> Teachers <- gen.teachers(n.teachers = n.teachers)
>>>>>>> str(Teachers$Teacher.ID)
>>>>>>> #Make a ‘schoolGrade’ object and then reshape
>>>>>>>
>>>>>>> schoolGrade <- expand.grid(grade = c(3,4,5),
>>>>>>>                            School.ID = paste0(gen.names(n =
>>>>>>> n.schools,
>>>>>>> which.names = "last"),
>>>>>>>                                               ' School'))
>>>>>>> # assign each of T teachers to 2 classrooms within a single school
>>>>>>> and grade
>>>>>>> cuttoff1<-n.teachers/2
>>>>>>> schoolGrade$A <- Teachers$Teacher.ID[1:cuttoff1]
>>>>>>> schoolGrade$B <- Teachers$Teacher.ID[1:cuttoff1]
>>>>>>> schoolGrade$C <- Teachers$Teacher.ID[(cuttoff1+1):n.teachers]
>>>>>>> schoolGrade$D <- Teachers$Teacher.ID[(cuttoff1+1):n.teachers]
>>>>>>>
>>>>>>> library(tidyr)
>>>>>>> schoolGrade <- gather(schoolGrade, Classroom, Teacher.ID, A:D) %>%
>>>>>>> full_join(Teachers, by="Teacher.ID")
>>>>>>>
>>>>>>> El problema es si quiero incrementar n.classroom incrementar de 4 a
>>>>>>> 20 (en
>>>>>>> lugar de A a D tener de A a T
>>>>>>>
>>>>>>> Gracias por la ayuda!
>>>>>>>
>>>>>>>         [[alternative HTML version deleted]]
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> R-help-es mailing list
>>>>>>> R-help-es en r-project.org
>>>>>>> https://stat.ethz.ch/mailman/listinfo/r-help-es
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Saludos,
>>>>>> Carlos Ortega
>>>>>> www.qualityexcellence.es
>>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>> Saludos,
>>>> Carlos Ortega
>>>> www.qualityexcellence.es
>>>>
>>>
>>
>>
>> --
>> Saludos,
>> Carlos Ortega
>> www.qualityexcellence.es
>>
>


-- 
Saludos,
Carlos Ortega
www.qualityexcellence.es

	[[alternative HTML version deleted]]



Más información sobre la lista de distribución R-help-es