R根据添加条件的特定列合并两个数据集

2024-04-03

Uwe 和 GKi 的答案都是正确的。 Gki 收到了赏金,因为 Uwe 迟到了,但 Uwe 的解决方案运行速度大约是原来的 15 倍

我有两个数据集,其中包含不同患者在多个测量时刻的分数,如下所示:

df1 <- data.frame("ID" = c("patient1","patient1","patient1","patient1","patient2","patient3"),
                  "Days" = c(0,25,235,353,100,538),
                  "Score" = c(NA,2,3,4,5,6), 
                  stringsAsFactors = FALSE)
df2 <- data.frame("ID" = c("patient1","patient1","patient1","patient1","patient2","patient2","patient3"),
                  "Days" = c(0,25,248,353,100,150,503),
                  "Score" = c(1,10,3,4,5,7,6), 
                  stringsAsFactors = FALSE)
> df1
        ID Days Score
1 patient1    0    NA
2 patient1   25     2
3 patient1  235     3
4 patient1  353     4
5 patient2  100     5
6 patient3  538     6

> df2
        ID Days Score
1 patient1    0     1
2 patient1   25    10
3 patient1  248     3
4 patient1  353     4
5 patient2  100     5
6 patient2  150     7
7 patient3  503     6

Column ID显示患者 ID、列Days显示测量时刻(自患者纳入后的天数)和列Score显示测量的分数。两个数据集显示相同的数据,但时间不同(df1 是 2 年前的数据,df2 具有相同的数据,但从今年开始更新)。

我必须比较每个患者和两个数据集之间每个时刻的分数。然而,在某些情况下Days变量随着时间的推移会有微小的变化,因此通过简单的连接来比较数据集是行不通的。例子:

library(dplyr)

> full_join(df1, df2, by=c("ID","Days")) %>% 
+   arrange(.[[1]], as.numeric(.[[2]]))

        ID Days Score.x Score.y
1 patient1    0      NA       1
2 patient1   25       2      10
3 patient1  235       3      NA
4 patient1  248      NA       3
5 patient1  353       4       4
6 patient2  100       5       5
7 patient2  150      NA       7
8 patient3  503      NA       6
9 patient3  538       6      NA

此处,第 3 行和第 4 行包含相同测量的数据(得分为 3),但未连接,因为Days列不同(235 与 248)。

问题:我正在寻找一种在第二列上设置阈值(例如 30 天)的方法,这将产生以下输出:

> threshold <- 30
> *** insert join code ***

        ID Days Score.x Score.y
1 patient1    0      NA       1
2 patient1   25       2      10
3 patient1  248       3       3
4 patient1  353       4       4
5 patient2  100       5       5
6 patient2  150      NA       7
7 patient3  503      NA       6
8 patient3  538       6      NA

此输出显示先前输出的第 3 行和第 4 行已合并(因为 248-235 Days第二个 df (248) 的。

要记住的三个主要条件是:

  • 阈值内的连续天数在同一个 df 中(第 1 行和第 2 行)不合并.
  • 在某些情况下,最多可以有四个值Days变量存在于同一数据框中,因此不应合并。可能的情况是,这些值之一确实存在于另一个数据帧的阈值内,并且必须将这些值合并。请参阅下面示例中的第 3 行。
  • 每个分数/天数/患者组合只能使用一次。如果合并满足所有条件但仍然可能存在双重合并,则应使用第一个合并。
> df1
        ID Days Score
1 patient1    0     1
2 patient1    5     2
3 patient1   10     3
4 patient1   15     4
5 patient1   50     5

> df2
        ID Days Score
1 patient1    0     1
2 patient1    5     2
3 patient1   12     3
4 patient1   15     4
5 patient1   50     5

> df_combined
        ID Days Score.x Score.y
1 patient1    0       1       1
2 patient1    5       2       2
3 patient1   12       3       3
4 patient1   15       4       4
5 patient1   50       5       5

编辑 Chinsoon12

> df1
          ID Days Score
 1: patient1    0     1
 2: patient1  116     2
 3: patient1  225     3
 4: patient1  309     4
 5: patient1  351     5
 6: patient2    0     6
 7: patient2   49     7
> df2
          ID Days Score
 1: patient1    0    11
 2: patient1   86    12
 3: patient1  195    13
 4: patient1  279    14
 5: patient1  315    15
 6: patient2    0    16
 7: patient2   91    17
 8: patient2  117    18
 

我将您的解决方案包装在如下函数中:

testSO2 <- function(DT1,DT2) {
    setDT(DT1);setDT(DT2)
    names(DT1) <- c("ID","Days","X")
    names(DT2) <- c("ID","Days","Y")
    DT1$Days <- as.numeric(DT1$Days)
    DT2$Days <- as.numeric(DT2$Days)
    DT1[, c("s1", "e1", "s2", "e2") := .(Days - 30L, Days + 30L, Days, Days)]
    DT2[, c("s1", "e1", "s2", "e2") := .(Days, Days, Days - 30L, Days + 30L)]
    byk <- c("ID", "s1", "e1")
    setkeyv(DT1, byk)
    setkeyv(DT2, byk)
    o1 <- foverlaps(DT1, DT2)
    
    byk <- c("ID", "s2", "e2")
    setkeyv(DT1, byk)
    setkeyv(DT2, byk)
    o2 <- foverlaps(DT2, DT1)
    
    olaps <- funion(o1, setcolorder(o2, names(o1)))[
        is.na(Days), Days := i.Days]
    
    outcome <- olaps[, {
        if (all(!is.na(Days)) && any(Days == i.Days)) {
            s <- .SD[Days == i.Days, .(Days = Days[1L],
                                       X = X[1L],
                                       Y = Y[1L])]
        } else {
            s <- .SD[, .(Days = max(Days, i.Days), X, Y)]
        }
        unique(s)
    },
    keyby = .(ID, md = pmax(Days, i.Days))][, md := NULL][]
    return(outcome)
}

结果是:

> testSO2(df1,df2)
          ID Days  X  Y
 1: patient1    0  1 11
 2: patient1  116  2 12
 3: patient1  225  3 13
 4: patient1  309  4 14
 5: patient1  315  4 15
 6: patient1  351  5 NA
 7: patient2    0  6 16
 8: patient2   49  7 NA
 9: patient2   91 NA 17
10: patient2  117 NA 18

正如您所看到的,第 4 行和第 5 行是错误的。的价值Score在 df1 中使用了两次 (4)。这些行周围的正确输出应如下所示,因为每个分数(在本例中为 X 或 Y)只能使用一次:

          ID Days  X  Y
 4: patient1  309  4 14
 5: patient1  315 NA 15
 6: patient1  351  5 NA

下面的数据框代码。

df1 <- data.frame(
  ID = rep(c("patient1", "patient2"), c(5L, 2L)),
  Days = c("0", "116", "225", "309", "351", "0", "49"),
  Score = 1:7
)

df2 <- data.frame(
  ID = rep(c("patient1", "patient2"), c(5L, 3L)),
  Days = c("0", "86", "195", "279", "315", "0", "91", "117"),
  Score = 11:18
)

听起来像是对现实但混乱的数据集进行的数据清理练习,不幸的是,我们大多数人以前都有过这样的经历。这是另一个data.table option:

DT1[, c("Xrn", "s1", "e1", "s2", "e2") := .(.I, Days - 30L, Days + 30L, Days, Days)]
DT2[, c("Yrn", "s1", "e1", "s2", "e2") := .(.I, Days, Days, Days - 30L, Days + 30L)]
byk <- c("ID", "s1", "e1")
setkeyv(DT1, byk)
setkeyv(DT2, byk)
o1 <- foverlaps(DT1, DT2)

byk <- c("ID", "s2", "e2")
setkeyv(DT1, byk)
setkeyv(DT2, byk)
o2 <- foverlaps(DT2, DT1)

olaps <- funion(o1, setcolorder(o2, names(o1)))[
    is.na(Days), Days := i.Days]

ans <- olaps[, {
        if (any(Days == i.Days)) {
            .SD[Days == i.Days, 
                .(Days=Days[1L], Xrn=Xrn[1L], Yrn=Yrn[1L], X=X[1L], Y=Y[1L])]
        } else {
            .SD[, .(Days=md, Xrn=Xrn[1L], Yrn=Yrn[1L], X=X[1L], Y=Y[1L])]
        }
    },
    keyby = .(ID, md = pmax(Days, i.Days))]

#or also ans[duplicated(Xrn), X := NA_integer_][duplicated(Yrn), Y := NA_integer_]
ans[rowid(Xrn) > 1L, X := NA_integer_]
ans[rowid(Yrn) > 1L, Y := NA_integer_]
ans[, c("md", "Xrn", "Yrn") := NULL][]

以下数据集的输出:

   ID Days  X  Y
1:  1    0  1 11
2:  1   10  2 12
3:  1   25  3 13
4:  1  248  4 14
5:  1  353  5 15
6:  2  100  6 16
7:  2  150 NA 17
8:  3  503 NA 18
9:  3  538  7 NA

OP编辑中第二个数据集的输出:

          ID Days  X  Y
 1: patient1    0  1 11
 2: patient1  116  2 12
 3: patient1  225  3 13
 4: patient1  309  4 14
 5: patient1  315 NA 15
 6: patient1  351  5 NA
 7: patient2    0  6 16
 8: patient2   49  7 NA
 9: patient2   91 NA 17
10: patient2  117 NA 18

数据(我从其他链接的帖子中添加了更多数据,并简化了数据以便于查看):

library(data.table)
DT1 <- data.table(ID = c(1,1,1,1,1,2,3),
    Days = c(0,10,25,235,353,100,538))[, X := .I]
DT2 <- data.table(ID = c(1,1,1,1,1,2,2,3),
    Days = c(0,10,25,248,353,100,150,503))[, Y := .I + 10L]

解释:

  1. 依次使用每个表作为左表执行 2 个重叠连接。

  2. 将右表中设置 NA 天之前的 2 个结果与左表中的结果合并。

  3. 按患者和重叠日期分组。如果存在相同的日期,则保留记录。否则使用最大日期。

  4. 每个分数只能使用一次,因此请删除重复的分数。

如果您发现此方法未给出正确结果的情况,请告诉我。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

R根据添加条件的特定列合并两个数据集 的相关文章

  • rmarkdown:pandoc:找不到 pdflatex

    当我在 Mac 上使用 render rmarkdown 从 Rmd 文件生成 pdf 文件时 出现错误消息 pandoc pdflatex not found pdflatex is needed for pdf output Error
  • R data.table %like% 带有逻辑 AND

    我正在尝试构建一个闪亮的搜索引擎应用程序 我根据搜索关键字返回 data table DT lt data table field c A B C A C D A D A B A D B C F B D K DT field like A
  • 为一列中的多行生成不同的随机数

    我得到了一列带有整数值 n 行 的列 我想生成满足特定条件的值的正态分布范围内的随机数 我尝试使用下面的代码 但它们太慢了 df members bd df members bd apply lambda x np random norma
  • 非常大的数据集的余弦相似度

    我在计算大量 100 维向量之间的余弦相似度时遇到问题 当我使用from sklearn metrics pairwise import cosine similarity I get MemoryError在我的 16 GB 机器上 每个
  • 按 data.table 中的所有列进行分组时,.SD 为空

    我无法获得一致的输出data table使用一致的语法 请参阅下面的示例 library data table d lt data table x c 1 1 2 2 y c 1 1 2 2 data table shown below x
  • 如何使用 pandas groupby 函数根据 groupby 值应用公式

    我的问题可能有点令人困惑 所以让我解释一下 我有一个信息数据框 我想按唯一订单 ID 对其进行分组 该 ID 将生成以下列 sum qty 每个订单 ID 执行的总金额 csv 这是每个订单 ID 的 csv 列的总和除以订单 ID 的已执
  • 当行数变化时如何绑定向量和矩阵

    在迭代算法中 我在每个步骤中确定要考虑的一行 几行或不考虑进一步计算 为了存储感兴趣的行 我必须绑定两个变量 X id 和 X val 我目前使用 cbind X id X val 当 X id 和 X val 都是矩阵时 它工作得很好 X
  • 无法使用 Shinyjs() 禁用闪亮的应用程序单选按钮

    我正在尝试禁用闪亮的应用程序单选按钮 趋势 input Product A input month All 使用Shinyjs包 但没有成功 我的 ui 页面定义为 ui lt fluidPage shinyjs useShinyjs pa
  • R,闪亮,应用程序之前的弹出窗口

    我正在开发一个闪亮的应用程序 它可以在启动时访问 MySQL 服务器并从中提取大量数据 这些数据稍后会在使用应用程序期间被过滤 由于传输的数据量相当大 第一个查询需要花费很多时间 这就是为什么我想创建一个对话框 弹出窗口或类似的东西 在应用
  • `knitr` 可以抑制 sql 块中的执行或输出吗?

    下面的文档运行 sql 并显示结果 我不希望显示任何输出 要么不运行该块 要么隐藏输出 有没有办法做到这一点 output html document Hide SQL Output First set up a temporary dat
  • 在 R 中使用 glmnet 和 dotCall64 的长向量

    我使用 glmnet 和 glmnetcr 来拟合序数回归模型 不幸的是 我的模型矩阵约为 640000 5000 这大于可以存储在 32 位整数中的大小 并且我遇到了其他人描述的相同问题 R 向量大小限制 C 中不支持长向量 参数 5 h
  • 如何在 R 中将 dd/mm/yy 转换为 yyyy-mm-dd

    我有一个向量 其日期值采用这种格式 dd mm yy 例如 27 06 16 我想将其转换为 yyyy mm dd 格式 例如 2016 06 27 以进行逻辑比较 我正在使用这个表达 as Date as character 27 06
  • 如何在 R 或 MATLAB 中为散点图创建阴影误差条“框”

    我想在 R 或 MATLAB 中创建一个简单的散点图 涉及两个变量 x 和 y 它们有与之相关的错误 epsilon x 和 epsilon y 然而 我不是添加误差线 而是希望在每个 x y 对周围创建一个 阴影框 其中框的高度范围从 y
  • 匹配较大向量中的序列

    我想要一个函数 它返回向量的匹配子序列的初始索引 例如 y lt c a a a b c multi match c a a y 1 1 2 multi match c a b y 1 3 我有一个粗略的实现 但我觉得我必须重新发明轮子 而
  • R:使用“lm”拟合线性模型时的对比错误

    我发现了在 R 中定义线性模型时对比错误 https stackoverflow com questions 18171246 error in contrasts when defining a linear model in r并遵循了
  • 将多个文件读取到多个数据框中

    在d 文件夹中 我有很多Stata文件 例如data aa 1 dta data aa 2 dta data aa 3 dta data bb 1 dta data bb 2 dta data bb 3 dta data cc 1 dta
  • 如何编辑多个 Pandas DataFrame 浮点列的字符串格式?

    我有一个pd DataFrame浮点数 import numpy as np import pandas as pd pd DataFrame np random rand 5 5 0 1 2 3 4 0 0 795329 0 125540
  • 如何使用电子表格中的第一行作为 Dataframe 列名称而不是 0 1 2...等?

    我希望我的数据框将第一行名称显示为数据框列名称 而不是从 0 等编号 我该如何执行此操作 我尝试使用 pandas 和 openpyxl 模块将我的 Excel 电子表格转换为数据框 import pandas as pd from ope
  • 将箱线图与 Wilcoxon 检验进行比较

    我正在使用 R 中的 ggplot2 包比较两组长度 不同的个体 和箱线图 我想比较这两个分布 但到目前为止我发现使用 wilcoxon 测试的唯一方法是 ggpubr 包中的 stat compare means 这是比较分布的正确方法吗
  • Rvest 从 select 中提取选项值和文本

    Rvest 选择选项 我认为用可重现的示例来解释是最简单的 网站 http www verema com vinos portada http www verema com vinos portada我想获取葡萄酒的类型 Tipos de

随机推荐