Цикл по подмножествам фрейма данных на основе двух условий - PullRequest
1 голос
/ 27 мая 2019

У меня следующая проблема: мне нужно запустить каждое подмножество фрейма данных на основе значения переменной, создавая новые записи для другой переменной в зависимости от 2 условий.

Фрейм данных (dt3)выглядит следующим образом: у меня есть 4 переменные (рождение, год, фамилия, имя, роль в домохозяйстве, роль и домохозяйство, чч).Весь набор делится или подмножествен переменной hh, которая собирает всех людей в одном домохозяйстве.Например, в моем примере ниже, первые 4 строки принадлежат домохозяйству «1».Кроме того, под переменной ролью указывается только глава домохозяйства.Остальные роли пусты и должны быть получены, и это то, что я пытаюсь сделать.Мой первый шаг - назначить роли «детям».Я думал об этом, выполняя цикл по всему набору данных и по каждому подмножеству (каждому значению hh).Если в каждой строке есть лицо, фамилия которого совпадает с фамилией главы домохозяйства и чей год рождения, по крайней мере, на 15 лет позже, чем у главы, то этот человек обозначается как «дети».

Исходный кадр данных:

birth_year       Name           role        hh

1877        Snijders    Head ofhousehold    1
1885        Marteen     NA                  1
1897        Snijders    NA                  1
1892        Zelstra     NA                  1
1878        Kuipers     Head of household   2
1870        Marteen     NA                  2
1897        Wals        NA                  2
1900        Venstra     NA                  2
1900        Lippe       Head of household   3
1905        Flachs      NA                  3
1920        Lippe       NA                  3
1922        Lippe       NA                  3

Итак, мне нужно запустить весь набор и каждое подмножество hh и выполнить следующие два условия: a.Если имя человека == имя руководителя, и б.Если год рождения человека имеет разницу в 15 лет и более с

головы, то этот человек - "дети".

До сих пор я пробовал несколько вещей.Поскольку я помещаю главную роль в первый ряд каждого домашнего хозяйства, я делаю это:

a) Вложенный цикл, в котором я пытаюсь запустить набор данных, а затем каждый чч.Для каждого чч я запускаю условия (сравнивая название каждой строки и год рождения с теми, что указаны в первой строке чч - головы -)

for (n in 1:unique(dt3$hh)){
  for (i in 1:length(which(dt3$hh==n)) ){ 
     mutate(dt3, role = ifelse( dt3$Name[[1,2]] == dt3$Name[[n,1]]    
     & dt3$birth_year[[n,i]] > dt3$birth_year[[n,1]], "children","NoA"))
      }
  }

Также б), я пытался сделать то же самое, но со списками.Сначала я разделил dt3 с помощью переменной hh

dt3 <- split(dt3, f = dt3$hh)

А затем

for (n in 1:dt3){
  mutate(dt3, role = ifelse( dt3$name [[n,i]] == dt3$name[[n,1]] &  
        dt3$birth_year[[n,i]] > dt3$birth_year[[n,1]],"children","NoA"))
  }

Безуспешно с двумя решениями, которые я изучал, и что я ожидал, это результат, подобный этому:

birth_year       Name           role        hh

1877        Snijders    Head ofhousehold    1
1885        Marteen     NA                  1
1897        Snijders    children            1
1892        Zelstra     NA                  1
1878        Kuipers     Head of household   2
1870        Marteen     NA                  2
1897        Wals        NA                  2
1900        Venstra     NA                  2
1900        Lippe       Head of household   3
1905        Flachs      NA                  3
1920        Lippe       children            3
1922        Lippe       children            3

Будут рады любым советам.

Заранее спасибо

Ответы [ 3 ]

1 голос
/ 29 мая 2019

Может быть, следующее быстрее:

Вы можете сначала заказать по чч и роли! = "HeadOfHousehold", который помещает главную роль в первый ряд каждого домашнего хозяйства, что вы уже сделали, но, возможно, вдругим способом, а затем проверьте с ave за чч, если имя совпадает, а разница в рождении больше, чем 14

dt3 <- read.table(header=T, text="birth_year      Name           role        hh
1877        Snijders    HeadOfHousehold    1
1885        Marteen     NA                  1
1897        Snijders    NA                  1
1892        Zelstra     NA                  1
1878        Kuipers     HeadOfHousehold   2
1870        Marteen     NA                  2
1897        Wals        NA                  2
1900        Venstra     NA                  2
1900        Lippe       HeadOfHousehold   3
1905        Flachs      NA                  3
1920        Lippe       NA                  3
1922        Lippe       NA                  3", as.is = T)

dt3 <- dt3[with(dt3, order(hh,role!="HeadOfHousehold")),]
dt3$role[with(dt3, as.logical(ave(Name, hh, FUN = function(x) x==x[1])) & ave(birth_year, hh, FUN = function(x) x>(x[1]+14)))] <- "children"
dt3

   birth_year     Name            role hh
1        1877 Snijders HeadOfHousehold  1
2        1885  Marteen            <NA>  1
3        1897 Snijders        children  1
4        1892  Zelstra            <NA>  1
5        1878  Kuipers HeadOfHousehold  2
6        1870  Marteen            <NA>  2
7        1897     Wals            <NA>  2
8        1900  Venstra            <NA>  2
9        1900    Lippe HeadOfHousehold  3
10       1905   Flachs            <NA>  3
11       1920    Lippe        children  3
12       1922    Lippe        children  3
1 голос
/ 06 июня 2019

Вы также можете просто использовать цикл for, например:

dt3 <- read.table(header=T, text="birth_year      Name           role        hh
1877        Snijders    HeadOfHousehold    1
1885        Marteen     NA                  1
1897        Snijders    NA                  1
1892        Zelstra     NA                  1
1878        Kuipers     HeadOfHousehold   2
1870        Marteen     NA                  2
1897        Wals        NA                  2
1900        Venstra     NA                  2
1900        Lippe       HeadOfHousehold   3
1905        Flachs      NA                  3
1920        Lippe       NA                  3
1922        Lippe       NA                  3", as.is = T)

dt3 <- dt3[with(dt3, order(hh,role!="HeadOfHousehold")),]

for(i in 1:nrow(dt3)) {
    if(!is.na(dt3$role[i]) & dt3$role[i] == "HeadOfHousehold") {
        hh <- dt3$hh[i]
        Name <- dt3$Name[i]
        birth_year <- dt3$birth_year[i]
    } else {
        if(hh == dt3$hh[i] & Name == dt3$Name[i] & dt3$birth_year[i] > birth_year+14) {dt3$role[i] <- "children"}
    }
}

dt3

   birth_year     Name            role hh
1        1877 Snijders HeadOfHousehold  1
2        1885  Marteen            <NA>  1
3        1897 Snijders        children  1
4        1892  Zelstra            <NA>  1
5        1878  Kuipers HeadOfHousehold  2
6        1870  Marteen            <NA>  2
7        1897     Wals            <NA>  2
8        1900  Venstra            <NA>  2
9        1900    Lippe HeadOfHousehold  3
10       1905   Flachs            <NA>  3
11       1920    Lippe        children  3
12       1922    Lippe        children  3
1 голос
/ 27 мая 2019

Вы можете сначала извлечь все «HeadOfHousehold» и объединить их с вашим dt3, а затем сравнить имена и год рождения.

dt3 <- read.table(header=T, text="birth_year      Name           role        hh
1877        Snijders    HeadOfHousehold    1
1885        Marteen     NA                  1
1897        Snijders    NA                  1
1892        Zelstra     NA                  1
1878        Kuipers     HeadOfHousehold   2
1870        Marteen     NA                  2
1897        Wals        NA                  2
1900        Venstra     NA                  2
1900        Lippe       HeadOfHousehold   3
1905        Flachs      NA                  3
1920        Lippe       NA                  3
1922        Lippe       NA                  3", as.is = T)


tt <- with(dt3[!is.na(dt3$role) & dt3$role=="HeadOfHousehold",], data.frame(a=birth_year, b=Name, hh))
me <- merge(dt3, tt, all.x=T)
me$role[me$Name==me$b & me$birth_year > me$a+14] <- "children"
me[names(dt3)]

1        1877 Snijders HeadOfHousehold  1
2        1885  Marteen            <NA>  1
3        1897 Snijders        children  1
4        1892  Zelstra            <NA>  1
5        1878  Kuipers HeadOfHousehold  2
6        1870  Marteen            <NA>  2
7        1897     Wals            <NA>  2
8        1900  Venstra            <NA>  2
9        1900    Lippe HeadOfHousehold  3
10       1905   Flachs            <NA>  3
11       1920    Lippe        children  3
12       1922    Lippe        children  3
...