socios domésticos partido sin bucle

votos
3

Estoy tratando de evitar el uso de una loopen mi intento de recodificar la variable de identificación de socios para el hogar.

hldiddenota el hogar, mientras que persidla persona en el hogar. La variable partnerindica el persidde la pareja y childindican si la fila es un niño.

Lo que falta en la variable partneres el persidde ambos socios.

Por ejemplo, para hldid == 1, el persid == 1tiene un valor de 0por partnersi bien debería ser 2.

Esta es la forma en que los datos se parece a:

> test
   hldid persid age sex relresp partner child
1      1      1  26   2       0       0     0
2      1      2  26   1       1       1     0
3      2      1  59   2       0       0     0
4      2      2  64   1       1       1     0
5      3      1  76   2       0       0     0
6      4      1  65   2       0       0     0
7      4      2  64   1       1       1     0
8      5      1  52   2       0       0     0
9      5      2  51   1       1       1     0
10     5      3  20   2      21       0     1
11     5      4  14   2      21       0     1
12     7      1  69   1       0       0     0
13     7      2  70   2       1       1     0

Me las arreglé para crear un lazo bastante feo, sin embargo, es demasiado lento para todo el conjunto de datos.

test$partnerREC = test$partner

for(i in 1:13){
  for(j in 1:13){

    if(
      test$hldid[i] == test$hldid[i+1] & # verify if household is the same 
      (test$persid[i] == test$partner[j])
    )

    {
      test$partnerREC[i] = test$persid[j] # put the persid for each partner
    }
  }
}

> test
   hldid persid age sex relresp partner child partnerREC
1      1      1  26   2       0       0     0          2
2      1      2  26   1       1       1     0          1
3      2      1  59   2       0       0     0          2
4      2      2  64   1       1       1     0          1
5      3      1  76   2       0       0     0          0
6      4      1  65   2       0       0     0          2
7      4      2  64   1       1       1     0          1
8      5      1  52   2       0       0     0          2
9      5      2  51   1       1       1     0          1
10     5      3  20   2      21       0     1          0
11     5      4  14   2      21       0     1          0
12     7      1  69   1       0       0     0          2
13     7      2  70   2       1       1     0          1 

¿Alguna idea de cómo podría utilizar data.tablepara resolver esto?

test = structure(list(hldid = c(1, 1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 7, 
7), persid = c(1, 2, 1, 2, 1, 1, 2, 1, 2, 3, 4, 1, 2), age = c(26, 
26, 59, 64, 76, 65, 64, 52, 51, 20, 14, 69, 70), sex = c(2, 1, 
2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2), relresp = c(0, 1, 0, 1, 0, 
0, 1, 0, 1, 21, 21, 0, 1), partner = c(0, 1, 0, 1, 0, 0, 1, 0, 
1, 0, 0, 0, 1), child = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 
0)), class = data.frame, row.names = c(NA, -13L))
Publicado el 27/11/2018 a las 16:59
fuente por usuario
En otros idiomas...                            


6 respuestas

votos
4

Una posible solución:

library(data.table)  # load the package
setDT(test)          # convert 'test' to a 'data.table'

test[, partnerREC := persid[c(pmin(2,.N):1,rep(0,(pmax(.N,2)-2)))] *
                       (persid %in% 1:2) *
                       (.N != 1)
     , by = hldid][]

lo que da:

> test
    hldid persid age sex relresp partner child partnerREC
 1:     1      1  26   2       0       0     0          2
 2:     1      2  26   1       1       1     0          1
 3:     2      1  59   2       0       0     0          2
 4:     2      2  64   1       1       1     0          1
 5:     3      1  76   2       0       0     0          0
 6:     4      1  65   2       0       0     0          2
 7:     4      2  64   1       1       1     0          1
 8:     5      1  52   2       0       0     0          2
 9:     5      2  51   1       1       1     0          1
10:     5      3  20   2      21       0     1          0
11:     5      4  14   2      21       0     1          0
12:     7      1  69   1       0       0     0          2
13:     7      2  70   2       1       1     0          1

Esta solución se basa en la suposición de (derivado de los datos de ejemplo) que sólo 'persid' 1 y 2 son socios, nada más alto son niños.

Lo que esto hace:

  • Agrupar por hldid
  • Cambiar el orden de las dos primeras personas en un hould pero sólo cuando hay más personas en un hogar con persid[c(pmin(2,.N):1,rep(0,(pmax(.N,2)-2)))]donde pminse utiliza para asegurar que un vector de longitud 1 está construida cuando un hogar tiene una sola persona.
  • Multiplicar que con (persid %in% 1:2)llegar Zores para los niños.
  • Multiplicar con que (.N != 1)para obtener un valor de cero para los hogares de una sola persona.
Respondida el 27/11/2018 a las 17:32
fuente por usuario

votos
1

Una solución de base R es más complicado que el de Jaap data.table solución .

Yo trabajo con una copia.

test2 <- test

Después de ejecutar el código en la pregunta, ejecute el siguiente.

test2$partnerREC <- test2$partner
sp <- split(test2, test2$hldid)
test2 <- lapply(sp, function(DF){
  i <- with(DF, which(persid %in% partner))
  j <- with(DF, which(partner %in% persid))
  #cat("i:", i, "\tj:", j, "\n")
  DF$partnerREC[i] <- DF$persid[j]
  DF
})
test2 <- do.call(rbind, test2)
row.names(test2) <- NULL

Ahora comparar ambos resultados.

identical(test, test2)
#[1] TRUE
Respondida el 27/11/2018 a las 17:47
fuente por usuario

votos
1
df <- data.frame(matrix(data = NA, ncol = 7))
names(df) <- names(test)

for(id in unique(test$hldid)){
  t <- test[test$hldid==id,]
  t$partner[t$persid == t$partner[t$partner!=0]] <- t$persid[which(t$partner!=0)]

  df <- rbind(df, t)
}

df <- df[-1,]
Respondida el 27/11/2018 a las 17:45
fuente por usuario

votos
0

Una loopsolución utilizandorcpp

Fuente la rcppsecuencia de comandos

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector HHgrid(CharacterVector hid, NumericVector persid, NumericVector partner, 
NumericVector partnerRec) {

  int nrows = hid.size();

  for (int i = 1; i < nrows - 1; i ++){
    for (int j = 0; j < nrows - 1; j++){

      if( (hid(i) == hid(i+1)) & ( persid(i) == partner(j) ) ){
        partnerRec(i) = persid(j); 
      }
    }
    Rcout << i << std::endl;     
  }
  return(partnerRec); 
}

y ejecutar la función

HHgrid(hid = test$hldid, persid = test$persid, partner = test$partner, partnerRec = test$partnerRec)

Sólo hay un pequeño problema con el primer caso (si usted sabe cómo solucionarlo)

Respondida el 28/11/2018 a las 12:18
fuente por usuario

votos
0

1. Cree su hoja.de.datos prueba

 library(tidyverse)

 test <- tribble(
            ~hldid, ~persid, ~age, ~sex, ~relresp, ~partner, ~child,
             1,      1,     26,   2,       0,       0,         0,
             1,      2,     26,   1,       1,       1,         0,
             2,      1,     59,   2,       0,       0,         0,
             2,      2,     64,   1,       1,       1,         0,
             3,      1,     76,   2,       0,       0,         0,
             4,      1,     65,   2,       0,       0,         0,
             4,      2,     64,   1,       1,       1,         0,
             5,      1,     52,   2,       0,       0,         0,
             5,      2,     51,   1,       1,       1,         0,
             5,      3,     20,   2,      21,       0,         1,
             5,      4,     14,   2,      21,       0,         1,
             7,      1,     69,   1,       0,       0,         0,
             7,      2,     70,   2,       1,       1,         0)

2. organizar () , group_by () , y mutar () venido a rescatar

test %>%
  # arrange the data in case the raw data did not 
  arrange(hldid, child, persid) %>%
  # group each household 
  group_by(hldid) %>%
  # match first and second household person as each other's partner
  mutate(partnerREC = ifelse(persid == first(persid), nth(persid, 2), first(persid))) %>%
  # correct partnerREC for child and single 
  mutate(partnerREC = ifelse(child == 1 | is.na(partnerREC), 0, partnerREC))
  # un-group it
  ungroup() 
Respondida el 27/11/2018 a las 19:09
fuente por usuario

votos
0

Se puede llegar a través de algunos dplyrpasos para unirse a los datos sobre sí mismo y actualizar el valor de la pareja cuando persid == partner.

test2 <- left_join(test, test %>% select(hldid, persid, partner) %>% filter(partner != 0), by=c("hldid")) %>%
  filter(persid.x == partner.y) %>%
  mutate(partner.x = persid.y)

Esto le dará la cabeza de familia con su socio Identificación del juego para arriba, pero que tendría que reunirse con esto a los datos originales (no estoy seguro de que el equivalente de SQL updateen dplyr jerga).

Respondida el 27/11/2018 a las 17:38
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more