R 对于不同的值和计数,如何在两个单独的数据帧中匹配行中的元素?

R 对于不同的值和计数,如何在两个单独的数据帧中匹配行中的元素?,r,dataframe,vectorization,matching,R,Dataframe,Vectorization,Matching,我有两个数据帧,下面复制了它们的真实数据。第一个数据帧如下所示: FirstDataFrame <- data.frame("GroupID" = c(1902, 1905, 1905, 1905, 1906, 1906, 1914, 1914, 1932, 1932, 1964, 1964, 1964), "SubjectID" = c(24626, 13300, 14126, 2619, 9

我有两个数据帧,下面复制了它们的真实数据。第一个数据帧如下所示:

FirstDataFrame <- data.frame("GroupID"   = c(1902, 1905, 1905, 1905, 1906, 1906, 1914, 1914, 1932, 1932, 1964, 1964, 1964), 
                         "SubjectID" = c(24626, 13300, 14126, 2619, 914, 872, 13325, 12539, 12597, 13314, 13343, 1723, 13333),
                         "Age"       = c(17, 13, 16, 17, 5, 9, 8, 14, 10, 13, 7, 14, 16))
SecondDataFrame
中的每个
AgeX
列对应于特定的一年年龄,如列名中所示

我的目标是,对于
FirstDataFrame
中的每个
GroupID

  • 提取年龄值(可能是向量)。请注意,
    GroupID
    中的一些年龄可能相同。例如,我可能有两个14岁的孩子
  • SecondDataFrame
    中,找到
    ID
    行,该行包含与
    GroupID
    中年龄匹配的最高频率,并且
    GroupID
    中的计数至少为1(或至少为2,在我将年龄加倍的情况下)。也就是说,找到列(向量索引?)匹配频率最高的
    OtherID
    行(或者向量,我考虑过为每个
    OtherID
    )指定一个向量)
  • GroupID
    中,将所选的
    OtherID
    分配给符合该标准的每个
    SubjectID
  • 将关联的
    AgeX
    列中与该
    OtherID
    的每个匹配项的计数减少1
  • GroupID
    中重复,直到所有
    SubjectID
    都与
    SecondDataFrame
    中的年龄匹配
  • 循环到下一个
    GroupID
  • 正如您在
    FirstDataFrame
    中所看到的,我有
    GroupID
    受试者,他们不能全部分配到
    SecondDataFrame
    中相同的
    OtherID
    。我在每个
    GroupID
    中也有不同数量的主题

    使事情更加复杂,,
    OtherID
    age列没有截止线,因此,如果所有
    OtherID
    Age11
    非零,则
    Age5
    Age10
    Age12
    Age17
    列之间的所有非零计数都是

    我已经清理了数据,使得
    SecondDataFrame
    中的每个
    AgeX
    计数至少包含
    FirstDataFrame
    中该年龄段相同数量的受试者。已设置
    FirstDataFrame
    SecondDataFrame
    中的最小和最大年龄值,以便这些值完全匹配

    如何确保最大匹配数并适当减少计数?我发现了一些与获得最大匹配数相关的问题/答案。但是:

  • 他们正在对一个向量与另一个向量进行简单测试,和/或
  • 它们不是减少匹配向量中的计数,而是简单地测试元素是否存在,或者一个向量中有多少值与另一个向量中的值匹配
  • 我可以使用嵌套的
    for()
    循环,但我一直在研究如何进行频率匹配和减少计数。我在想我需要在
    GroupID
    中最年轻的年龄开始比赛,并在
    GroupID
    中随着年龄的增长而工作,而这正是我陷入困境的地方

    编辑:最终确定的
    FirstDataFrame
    如下所示:

    FirstDataFrame <- data.frame("GroupID"   = c(1902, 1905, 1905, 1905, 1906, 1906, 1914, 1914, 1932, 1932, 1964, 1964, 1964),
                             "SubjectID" = c(24626, 13300, 14126, 2619, 914, 872, 13325, 12539, 12597, 13314, 13343, 1723, 13333),
                             "Age"       = c(17, 13, 16, 17, 5, 9, 8, 14, 10, 13, 7, 14, 16), 
                             "OtherID"   = c(2, 3, 3, 3, 6, 6, 6, 3, 6, 6, 6, 3, 3)
    

    FirstDataFrame这是一个很长很难解决的问题,我不确定我是否回答了所有问题

    下面是我解决这个问题的方法,首先根据
    GroupID
    拆分
    FirstDataFrame
    ,得到一个列表:

    split_df <- split(FirstDataFrame, FirstDataFrame$GroupID)
    split_df
    #$`1902`
    #  GroupID SubjectID Age
    #1    1902     24626  17
    #
    #$`1905`
    #  GroupID SubjectID Age
    #2    1905     13300  13
    #3    1905     14126  16
    #4    1905      2619  17
    #
    #$`1906`
    #  GroupID SubjectID Age
    #5    1906       914   5
    #6    1906       872   9
    #
    #$`1914`
    #  GroupID SubjectID Age
    #7    1914     13325   8
    #8    1914     12539  14
    # ...
    
    同样,使用
    apply()
    ,我们可以计算出三个子行出现的可能性(注意
    props
    中它变成了列)

    最后,转到
    SecondDataFrame
    中的相应行,用这组孩子的年龄频率减去年龄频率:

    SecondDataFrame[SecondDataFrame$OtherID == chosenID, 2:14] <- 
        SecondDataFrame[SecondDataFrame$OtherID == chosenID, 2:14] - freq
    

    SecondDataFrame[SecondDataFrame$OtherID==chosenID,2:14]无法理解您从目标2开始想要什么。将问题分解成更小的、可管理的规模是有帮助的。举个例子有用吗?首先,假设对于
    GroupID
    1905,你有一个
    Age
    向量13,16,17;那么您是否应该在
    SecondDataFrame
    中选择具有最高值
    Age13
    Age16
    Age17
    ?这是否意味着选择
    OtherID
    2是因为
    Age16
    是127?我已经用更多信息更新了这个问题。将有一个概率匹配,如何做到这一点我还不确定-这将取决于如何匹配完成。主要问题是确保同一
    GroupID
    中的所有孩子都匹配到同一所学校,而这是年龄要求的。然后将每个匹配的
    OtherID
    减少1。而
    OtherID
    计数中任何年龄的0都会覆盖该
    GroupID
    子集合的所有其他匹配项。我还考虑过根据最小计数进行选择。这意味着我不会有很多比赛问题,因为我在一个年龄段有很多0。我需要用大量的综合构建的数据来测试这一点,看看是什么打破了匹配。但首先我必须能够做匹配!谢谢,我想知道我是否可以保留第二个数据帧作为数据帧,而不是(在我目前的情况下)创建15个不同的向量。我相信在“基本”R数据帧下答案是肯定的。如果是
    tibble
    i = 2
    ages <- split_df[[i]]$Age
    ages
    #[1] 13 16 17
    
    ind_ages <- ages - 4 # "Indexize" ages: Age 5 become 1, 6 become 2, ..., 17 become 13
    ind_ages
    #[1]  9 12 13
    
    freq <- tabulate(ind_ages, nbins = 13)
    freq
    #[1] 0 0 0 0 0 0 0 0 1 0 0 1 1
    
    props <- apply(SecondDataFrame[,2:14], 1, function (x) x/sum(x))
    props
    #            [,1]      [,2]      [,3]      [,4]       [,5]       [,6]
    #Age5  0.00000000 0.0000000 0.0000000 0.1222222 0.14814815 0.14736842
    #Age6  0.00000000 0.0000000 0.0000000 0.1333333 0.09876543 0.13684211
    #Age7  0.00000000 0.0000000 0.0000000 0.1333333 0.11111111 0.11052632
    #Age8  0.00000000 0.0000000 0.0000000 0.1000000 0.13580247 0.13157895
    #Age9  0.00000000 0.0000000 0.0000000 0.1333333 0.08641975 0.11842105
    #Age10 0.00000000 0.0000000 0.0000000 0.1333333 0.13580247 0.10789474
    #Age11 0.05428571 0.0000000 0.0000000 0.1000000 0.09876543 0.11052632
    #Age12 0.04000000 0.0000000 0.0000000 0.1444444 0.14814815 0.10263158
    #Age13 0.15142857 0.1529412 0.1522936 0.0000000 0.03703704 0.03421053
    #Age14 0.19714286 0.1980392 0.2660550 0.0000000 0.00000000 0.00000000
    #Age15 0.16857143 0.2235294 0.2348624 0.0000000 0.00000000 0.00000000
    #Age16 0.21714286 0.2490196 0.1963303 0.0000000 0.00000000 0.00000000
    #Age17 0.17142857 0.1764706 0.1504587 0.0000000 0.00000000 0.00000000
    
    likelihood <- apply(props, 2, function (x) dmultinom(freq, size = sum(freq), prob = x))
    likelihood
    #[1] 0.03382111 0.04032567 0.02699215 0.00000000 0.00000000 0.00000000
    
    prob_OtherID <- likelihood / sum(likelihood)
    prob_OtherID
    #[1] 0.3344025 0.3987156 0.2668819 0.0000000 0.0000000 0.0000000
    
    chosenID <- sample(SecondDataFrame$OtherID, size = 1, prob = prob_OtherID)
    split_df[[i]]$OtherID <- chosenID
    
    SecondDataFrame[SecondDataFrame$OtherID == chosenID, 2:14] <- 
        SecondDataFrame[SecondDataFrame$OtherID == chosenID, 2:14] - freq