根据两个条件循环遍历数据帧的子集

时间:2019-05-27 15:33:00

标签: r list loops if-statement mutate

我有以下问题:我需要运行一个数据帧的每个子集-基于变量的值-根据2个条件为另一个变量创建一个新条目。

数据帧(dt3)如下:我有4个变量(出生年,姓–名称-,在家庭中的角色-角色-和家庭-hh-)。整个集由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子集,并执行以下两个条件: 一种。如果此人的名字==头部的名字,并且 b。如果该人的出生年份与头部的差异大于或等于15岁

那么这个人就是“孩子”。

到目前为止,我一直在尝试几种方法。当我将领导角色放在每个家庭的第一行时,我正在这样做:

a) 嵌套循环,我尝试在其中运行数据集,然后每次运行hh。对于每hh,我都运行条件(通过将每行的名称和出生年份与hh第一行的内容(头)进行比较)

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"))
      }
  }

也b),我尝试执行相同操作,但使用列表。我首先通过hh变量

分割dt3
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 个答案:

答案 0 :(得分:1)

您可以先提取所有“ 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

答案 1 :(得分:1)

您也可以简单地使用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

答案 2 :(得分:0)

也许以下速度更快:

您可以先通过hh和role!=“ HeadOfHousehold”进行订购,该操作将head角色放置在每个家庭的第一行中,您已经做过的事情,但可能以其他方式做了,然后用{{1} } / hh(如果名称相同,并且birth_year的差异大于14

ave