首页 > 解决方案 > 具有条件、迭代计算和公差匹配的复杂 ID 分配

问题描述

我正在尝试编写一个相当复杂的迭代匹配函数,但我淹没在 ifelse 和不起作用的函数中。不幸的是,我没有任何人可以提出想法,因此感谢任何支持或想法。

我的数据结构

我的每一行数据都是一个包含许多变量的观察结果,相关变量包含在这个例子中。观察具有指定Sample_Name的 、Matching_Group对应于样本名称的 、 的测量值Time和主观的,该主观Assigned_idx是从数据清理的早期部分中部分完成的。每个观察到Sample_Name的可以包含 0-7 个观察,但Matching_Group总是包含 7 个观察。

structure(list(Sample_Name = c("A", "A", "A", "A", "A", "B", "B", "B", 
"B", "B", "B", "QQ", "QQ", "QQ", "QQ", "QQ", "QQ", "QQ", "SS", 
"SS", "SS", "SS", "SS", "SS", "SS"), Matching_Group = c("QQ", 
"QQ", "QQ", "QQ", "QQ", "SS", "SS", "SS", "SS", "SS", "SS", "QQ", 
"QQ", "QQ", "QQ", "QQ", "QQ", "QQ", "SS", "SS", "SS", "SS", "SS", 
"SS", "SS"), Time = c(1, 1.1, 1.2, 1.4, 1.6, 7.203, 7.395, 
7.5, 7.6, 7.7, 7.802, 1, 1.102, 1.2, 1.3, 1.398, 1.501, 1.6, 
7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8), Assigned_idx = c(NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, 2, 3, 4, 5, 6, 7, 1, 2, 
3, 4, 5, 6, 7)), row.names = c(NA, -25L), class = c("tbl_df", 
"tbl", "data.frame"))


Sample_Name Matching_Group  Time        Assigned_idx

A           QQ              1.000   
A           QQ              1.100   
A           QQ              1.200   
A           QQ              1.400   
A           QQ              1.600   
B           SS              7.203   
B           SS              7.395   
B           SS              7.500   
B           SS              7.600   
B           SS              7.700   
B           SS              7.802   
QQ          QQ              1.000       1
QQ          QQ              1.102       2
QQ          QQ              1.200       3
QQ          QQ              1.300       4
QQ          QQ              1.398       5
QQ          QQ              1.501       6
QQ          QQ              1.600       7
SS          SS              7.200       1
SS          SS              7.300       2
SS          SS              7.400       3
SS          SS              7.500       4
SS          SS              7.600       5
SS          SS              7.700       6
SS          SS              7.800       7

我的问题

对于每个观察(行),我想计算对应的行之间的比率。每个都会有一个指定的唯一值,计算需要等于 +/- 一些容差。如果计算出的比率与特定于组的预定义比率匹配,我想从属于观察的行中提取并分配,并将其分配给观察。如果不是,请使用相同的观察值和下一行中的重复计算。重复直到每个观察值在.TimeMatching_GroupMatching_GroupTime_RatioAssigned_idxMatching_GroupTimeTimeMatching_GroupAssigned_idx

示例:在此数据集中,对于两者Matching_Group应该Time_Ratio等于1.000 +/- 0.0020。在我的真实数据集中,每个单独的表中都会有唯一的Time_Ratio值。Matching_Group因此,对于带有Time=的第 3 行1.200Matching_Group就是QQ。当我们计算与第一次QQ观察到的时间的比率时,1.200/1.000 = 1.200这超出了我们定义的容差 --> 下一次观察到的时间QQ1.200/1.102 = 1.089...再次超出我们的容忍范围。最后,1.200/1.200 = 1.000这确实在我们指定的容忍范围内Matching_Group。在Matching_Group具有匹配率的观察行中,Assigned_idx列保持3。我们取这个值,并将其映射到Assigned_idx第 3 行的列。然后对第 4 行重复此操作并迭代该过程。

期望的结果:

Sample_Name Matching_Group  Time        Assigned_idx    Time_Ratio (Sample:Matching) 

A           QQ              1.000       1               1.0000
A           QQ              1.100       2               0.9982
A           QQ              1.200       3               1.0000
A           QQ              1.400       5               1.0014
A           QQ              1.600       7               1.0000
B           SS              7.203       1               1.0004
B           SS              7.395       3               0.9993
B           SS              7.500       4               1.0000
B           SS              7.600       5               1.0000
B           SS              7.700       6               1.0000
B           SS              7.802       7               1.0003
QQ          QQ              1.000       1               1.0000
QQ          QQ              1.102       2               1.0000
QQ          QQ              1.200       3               1.0000
QQ          QQ              1.300       4               1.0000
QQ          QQ              1.398       5               1.0000
QQ          QQ              1.501       6               1.0000
QQ          QQ              1.600       7               1.0000
SS          SS              7.200       1               1.0000
SS          SS              7.300       2               1.0000
SS          SS              7.400       3               1.0000
SS          SS              7.500       4               1.0000
SS          SS              7.600       5               1.0000
SS          SS              7.700       6               1.0000
SS          SS              7.800       7               1.0000

我已经尝试使用 dplyr 来解决这个问题,因为我认为它应该能够处理我想要完成的事情(也许 purrr 更适合?)。不幸的是,我似乎无法在 ifelse 和 for 函数中适当地对条件和表达式进行排序。我的尝试包括将 %>% 变异与比率计算、data.table::shift 等混合在一起,但我似乎无法让它与我的条件参数一起使用。此外,如果它是相关的,在我的真实数据中将有约 50 个“名称”和约 25 个匹配组。我将有第二个数据源列出匹配的组名和相应的比率,但在此示例中未包含此类详细信息。

老实说,我很难过,任何想法都值得赞赏。

标签: rdplyr

解决方案


像这样的东西应该工作:

#!/usr/bin/R

a = structure(list(Sample_Name = c("A", "A", "A", "A", "A", "B", "B", "B", 
"B", "B", "B", "QQ", "QQ", "QQ", "QQ", "QQ", "QQ", "QQ", "SS", 
"SS", "SS", "SS", "SS", "SS", "SS"), Matching_Group = c("QQ", 
"QQ", "QQ", "QQ", "QQ", "SS", "SS", "SS", "SS", "SS", "SS", "QQ", 
"QQ", "QQ", "QQ", "QQ", "QQ", "QQ", "SS", "SS", "SS", "SS", "SS", 
"SS", "SS"), Time = c(1, 1.1, 1.2, 1.4, 1.6, 7.203, 7.395, 
7.5, 7.6, 7.7, 7.802, 1, 1.102, 1.2, 1.3, 1.398, 1.501, 1.6, 
7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8), Assigned_idx = c(NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, 1, 2, 3, 4, 5, 6, 7, 1, 2, 
3, 4, 5, 6, 7)), row.names = c(NA, -25L), class = c("tbl_df", 
"tbl", "data.frame"));

tol = 0.002;

a$Time_Ratio <- NA;

for (i in 1:nrow(a)) {
  s_name <- a[i, "Sample_Name"];
  mg     <- a[i, "Matching_Group"];
  s_time <- a[i, "Time"];

  for (j in 1:nrow(a)) {
    mg_name <- a[j, "Sample_Name"];
    if (mg_name == mg) {
      mg_time <- a[j, "Time"];
      time_ratio = s_time/mg_time;
      if (abs(time_ratio - 1.0) < tol) {
        a[i, "Assigned_idx"] <- a[j, "Assigned_idx"];
        a[i, "Time_Ratio"] <- time_ratio;
        break;
      }
    }
  }
}

print(a);

推荐阅读