如何在R中将一列的信息相互链接

xxhby3vn  于 2023-10-13  发布在  其他
关注(0)|答案(2)|浏览(99)

我有一个数据集,大约有150万个人可以用“家庭ID”在他们的家庭中区分出来。该数据集有一个列(关系),该列根据家庭成员与户主的关系指定家庭成员之间的关系。

library(tidyverse)
    sample <- tibble( 
    household.ID = c(11015015988, 11015015988, 11015015988 , 
    11015015988 , 11015015988, 
    11015015988, 11015015988, 11015015988,228979641, 
    228979641, 228979641 ,228979641),
    member.ID= c(1101502683 ,11015026954,11015027098,11015027231 
    ,11015027353,11015027484 
    ,11015027615 ,11015027751,228992311,228996137,229001877,229005869),
    relationship = c(1,2,3,3,3,3,2,3,1,3,2,2),
    gender = c(1,2,1,2,1,1,2,2,1, 2, 2 , 2),
    age = c(54,54,30,26,23,31,20,2, 60,12,34,62),
    marriage.status= c(1,1,4,4,4,1,1,NA, 1, 4, 1,1),
    children.ever.born= c(NA,8,NA,NA,NA,NA,1,NA,NA,NA,1,1),
    living.children  = c(NA,8,NA,NA,NA,NA,1,NA,NA,NA,1,1))

“代码1”指户主;“代码2”是头的妻子;“代码3”是头的子;因此,在家中拥有“代码2”的人就是“代码3”的母亲。我需要链接“code 2”和“code 3”,以便在每个家庭ID中,关系值3标识来自同一个家庭的成员ID,关系值为2。通过下面的代码,我可以这样做。

sample2 <- select(sample, 1:8) 
    spouse_links <- left_join(relationship = "many-to-many",
    sample2 %>% filter(relationship == 3),
    sample2 %>% filter(relationship == 2, !is.na(living.children)) %>%
    rename(member.ID.mother = member.ID), join_by(household.ID)) %>%
    filter(!is.na(relationship.y)) %>%
    select(1:8, member.ID.mother)

然而,我对一夫多妻制是习俗的家庭有一个问题(与多个配偶结婚的做法)。在这样的家庭中,我们面对的是关系栏中两个或两个以上的“代码2”;结果,R代码将所有“代码3”链接到两个“代码2”。为了澄清,请考虑下表:

根据该表,我们可以发现,儿童与母亲的联系是基于家庭中的接近程度。例如,行2是行3、4、5和6中的子节点的母亲,并且行7是行8的母亲;然而,情况并非总是如此,有时母亲的年龄和“活着的孩子”可能会有所帮助。我需要像下面这样到达一张table:

我真的很感激你能提供的任何帮助。

mnemlml8

mnemlml81#

可能有一种更优雅的方法来实现这一点,但您可以使用cumsum(sample$relationship == 2)来创建指标,按家庭在内部分解值。
dplyr管道中,这可以应用于将每个组分成一个列表(通过group_split),然后使用map创建mother.member.ID变量:

library(dplyr)

sample %>%
  mutate(row = row_number(),
         grp = cumsum(relationship == 2),
         .by = household.ID) %>%
  filter(relationship != 1) %>%
  group_by(household.ID, grp) %>%
  group_split() %>%
  purrr::map(~filter(., any(relationship == 2)) %>% 
               mutate(mother.member.ID = member.ID[relationship %in% 2]) %>% 
        filter(relationship == 3)) %>%
  bind_rows() %>% select(-grp)

#  household.ID   member.ID relationship gender   age marriage.status children.ever.born living.children   row mother.member.ID
#         <dbl>       <dbl>        <dbl>  <dbl> <dbl>           <dbl>              <dbl>           <dbl> <int>            <dbl>
#1  11015015988 11015027098            3      1    30               4                 NA              NA     3      11015026954
#2  11015015988 11015027231            3      2    26               4                 NA              NA     4      11015026954
#3  11015015988 11015027353            3      1    23               4                 NA              NA     5      11015026954
#4  11015015988 11015027484            3      1    31               1                 NA              NA     6      11015026954
#5  11015015988 11015027751            3      2     2              NA                 NA              NA     8      11015027615
sgtfey8w

sgtfey8w2#

在OP中,不清楚member.ID排序顺序提供了什么信息。这表明,排序顺序是相关的,以表明那些报告后,母亲报告的孩子是以前报告的母亲的孩子-除非在这种情况下,这是不正确的。
我认为这是一个有问题的假设,我们应该知道它是可靠的(因为数据集信息表告诉我们它是);或者不是。
如果这是可靠的,那么当儿童在任何母亲被报告之前被报告时,这可能意味着孩子的母亲已经不在人世,或者只是不在家里生活。在这种情况下,它质疑业务政策假设,即家庭中所有儿童都有母亲,以及应如何进行分析?
如果member.ID排序顺序不可靠,那么在任何分配中使用它就没有任何价值,任何分配都是巧合,或者反映了调查员调查住户的随意顺序。
下面的解决方案提供了OP中要求的“第一个母亲”的答案,假设member.ID的排序顺序对完整性有意义。但我更喜欢根据年龄和出生的孩子数量来进行启发式的研究。

library(data.table)
setDT(sample)

定义了mother.ID变量,并在数据集中划分母亲和孩子的子集

sample[,mother.ID:=as.numeric(NA)]
mothers <- sample[relationship==2]
children <- sample[relationship==3]

对于那些从未有过孩子的母亲来说,

mothers[is.na(children.ever.born),
        children.ever.born:=0]

mothers <- mothers[children.ever.born>=0]

在每个家庭中,交叉连接所有可能的母亲和所有可能的子女数据。表的.EACHI命名法以一种内存高效(快速)的方式实现了这种组内交叉连接

motherschildren <- children[,
                            .(household.ID,
                              child.ID=member.ID,
                              child.age=age)][mothers[,.(household.ID,
                                                         mother.ID=member.ID,
                                                         mother.age=age,
                                                         children.ever.born)],
                                    .(mother.ID,
                                      child.ID,
                                      child.age,
                                      mother.age,
                                      children.ever.born),
                                    on=.(household.ID),
                                    by=.EACHI]

为了OP的完整性,如果我们假设member.ID排序顺序是相关的,那么将first.mother.ID分配给每个孩子。然后继续剩下的解决方案,将最可能的母亲分配给每个孩子,其中first.mother.ID产生NA。但除非数据规格明确说明这一点,否则我不认为这是一个强有力的假设。

if (FALSE) {   
      setorder(motherschildren,
            -household.ID,
            child.ID,
            -mother.ID)
       motherschildren[,
                    first.mother.ID:=mother.ID[mother.ID < child.ID][1],
                    by=.(child.ID)]
        sample[unique(motherschildren[,.(household.ID,
                                     child.ID,
                                     first.mother.ID)]),
           mother.ID:=i.first.mother.ID,
           on=.(household.ID,
                member.ID=child.ID)]
        motherschildren <- motherschildren[is.na(first.mother.ID)==TRUE] 
}

在缺乏关于数据集的已知信息以及数据如何在数据集中收集和表示的情况下,我们必须根据最佳猜测将孩子分配给母亲。年龄是一个很好的因素,可以排除可能性(例如,孩子比母亲大)。
根据母亲和孩子之间的年龄差异创建一个“年龄.分数”,根据主要生育年龄将孩子按母亲进行排名,例如,给定两名妇女,其中一名在孩子出生时为25岁,另一名为37岁,假设25岁生了孩子。

motherschildren[,age.difference:=mother.age-child.age]

motherschildren[,
                age.score:=fcase(age.difference <= 0,as.numeric(NA),
                                 age.difference >= 20 & age.difference <= 30,1,
                                 age.difference >= 17,2,
                                 default=3)]

看看这组不太可能的孩子中是否有任何数据点可能会很有趣?

motherschildren[age.score==3]

根据年龄筛选出不可能的母亲

motherschildren <- motherschildren[is.na(age.score)==FALSE]

除了年龄,我们还知道每个母亲生了多少个孩子。创建一个排名。分数,以过滤出可能的孩子超出了妇女所生的数量。例如,如果她生了两个孩子,而这个家庭有10个孩子,我们知道她不能成为两个以上的母亲。rank.score将根据age. score标识第一个子项的数量(在本例中为2)。然而,这是一个值得怀疑的假设,因为家庭中的所有女性都不太可能连续生孩子。但我认为这是一个更好的假设比什么都没有。使用<= children.ever.born+1进行评分可能会在不同的潜在母亲中产生更多的不确定性?
根据每个母亲可能的孩子相对于孩子的年龄对数据集进行排序(即,如果她生了那个孩子,那么她将先生最大的孩子,最近生最小的孩子)

setorder(motherschildren,
         household.ID,
         mother.ID,
         -child.age)

motherschildren[,
                rank.score:=FALSE]

motherschildren[,
                rank.score:= (1:.N) <= children.ever.born, #children.ever.born+1 may be a better assumption?
                by=.(household.ID,
                     mother.ID)]

筛选出排名分数超过母亲所生子女数量的可能子女。

motherschildren <- motherschildren[rank.score==TRUE]

根据年龄.score,按每个孩子的可能母亲对数据集进行排序,其中年龄.score最高的可能母亲将首先排序
按每个家庭和每个孩子分组,并选择第一个可能的母亲作为最有可能生下该孩子的母亲。

setorder(motherschildren,
         household.ID,
         child.ID,
         age.score)

motherschildren <- motherschildren[,
                                   .(mother.ID=mother.ID[1]),
                                   by=.(household.ID,
                                        child.ID)]

将选定的mother.ID值重新连接到整个数据集中。

sample[motherschildren,
       mother.ID:=i.mother.ID,
       on=.(household.ID,
            member.ID=child.ID)]

看看这个子集中是否有任何数据点可能会很有趣?

sample[relationship==3 & is.na(mother.ID)]

出于数据分析的目的,将所有已识别的母亲及其子女的mother.group变量创建为列变量

sample[,mother.group:=as.numeric(NA)]
sample[relationship != 1,
       mother.group:=.GRP,
       by=.(household.ID,
            ifelse(is.na(mother.ID),
                   member.ID,
                   mother.ID))]

setorder(sample,
         -household.ID,
         mother.group,
         relationship)

相关问题