精华内容
下载资源
问答
  • 对照匹配
    2022-06-12 20:16:42

    R语言使用epiDisplay包的matchTab函数计算配对病例对照暴露研究(病例和对照组进行配对,1:1或者1:m)的表格、并基于MLE极大似然估计方法计算优势比及其置信区间

    目录

    更多相关内容
  • 这周接到一个活,因为某个课题研究需要,须把脑卒中患者的名单和一份健康人(对照)名单按照”性别相同,乡镇地址相同,年龄相差3岁以内“作为匹配条件进行1:1的匹配,现将思考及实现的过程逐一记录并在此分享,希望...

    这周接到一个活,因为某个课题研究需要,须把脑卒中患者的名单和一份健康人(对照)名单按照”性别相同,乡镇地址相同,年龄相差3岁以内“作为匹配条件进行1:1的匹配,现将思考及实现的过程逐一记录并在此分享,希望能给大家有所借鉴与帮助。

    拿到这份数据后首要的工作是熟悉数据和提取关键信息。这两份数据都是保存于Excel中的单表结构的数据(没有复杂的表关联),脑卒中患者1300多条,健康人8200多条,做1:1匹配绰绰有余;主索引采用身份证号,关键信息有”姓名、性别、年龄和乡镇地址“。然后考虑输出的结果的格式,Excel,表单中列入脑卒中患者的全部数据,最后增加一列存放匹配的对照者身份证号。

    接下来开始动手编程,第一步引用pandas导入数据。其中路径前的"r"和中文前的"u"不可少,可能是因为我还在用Python2的关系。

    # -*- coding: gbk -*-
    #!/usr/bin/env python
    # __author__ = 'PanJin'
    
    import pandas as pd
    case=pd.read_excel(r'D:\并发症数据库(实验室检测筛选).xls',sheet_name=u'心脑')
    ctrl=pd.read_excel(r'D:\并发症数据库(实验室检测筛选).xls',sheet_name=u'对照(不包含肿瘤)')
    

    动手分析之前一直有个担心,作为索引的身份证号是否会有重复的记录,果然我的担心应验了,查重发现健康个案的身份证号有4组是重复的(在Excel里用公式查的,所以没有上代码),同时发现8000多人中有部分因为失访,检查结果有大量缺失,于是和重复的身份证号进行了删除。(代码中的身份证号进行了脱敏处理)

    ctrl_=ctrl[(ctrl.sfzh !='33042119320221####') & (ctrl.sfzh !='33072219560522####') & (ctrl.sfzh !='33042119381031####') & (ctrl.sfzh !='33042119390824####') & (ctrl.HDLC2 !='#NULL!')]
    

    刚开始打算用pandas里的merge直接解决战斗的,但是发现问题想的太简单了,因为根据匹配条件”性别相同,乡镇地址相同,年龄相差3岁以内“,直接merge的结果一定会有很多一对多甚至多对多的笛卡尔积产生,而对这些笛卡尔积好像没有太好的自动化处理方案,因此我在开始就放弃了这种尝试。所以我的计划是采用Python里的for循环来解决。

    解题思路如下:

    首先从脑卒中患者清单中取第一条,在健康对照中按条件匹配所有适合的名单,然后取第一条(或者调用random函数来随机一下),已匹配的健康对照从大名单中删除,然后进行再取第二条脑卒中患者重复以上过程直至循环到最后。最终将形成3个名单,1.匹配完成名单;2.患者未匹配名单;3.健康对照未匹配名单。

    另外考虑匹配优化的问题,我把这个循环分成了两轮,第一轮中匹配条件为”性别相同,乡镇地址相同,年龄相等“,第二轮中为”性别相同,乡镇地址相同,年龄相差3岁以内“,这样能保证条件接近的健康对象优先进入匹配。

    接下来是实现的步骤:

    首先确定能取到数据库里的目标值,这个步骤很重要,Python中取值是件很头疼的事情,数据格式有很多种,在Pandas里有DataFrame、Series,另外还有list、object等格式,只时候看起来是一个单个的值,但是却不能直接做比较,因此通过取值调试,可以发现并处理很多编码过程中的错误。

    name=case['name'].values[0]
    sfzh=case['sfzh'].values[0]
    sex=case['sex'].values[0]
    age=case['age'].values[0]
    xz=case['xz'].values[0]
    # 取值
    In[1]
    print name
    print sfzh
    print sex
    print age
    print xz
    
    Out[1]
    蒋*英
    3304211941########
    2
    75
    西塘

    按照以上的取值,在对照中寻找匹配记录。

    In[2]
    print ctrl_[(ctrl_.sex==2) & (ctrl_.age==age) & (ctrl_.xz==xz)]
    Out[2]
    
         area name                sfzh  ...   GLU2   TC2  LDLC2
    1115   js  吕*英  3304111941########  ...      0     5      2
    2039   js  彭*花  3304211941########  ...      0  3.74   1.52
    ...
    7028   js  孔*花  3304211941########  ...      0  4.21   1.75
    
    [9 rows x 43 columns]
    

    将具体值替换为代码,同时取第一条匹配记录,并对身份证号取值。

    In[3]
    print ctrl_[(ctrl_.sex==case['sex'].values[0]) & (ctrl_.age==case['age'].values[0]) & (ctrl_.xz==case['xz'].values[0])]['sfzh'].values[0]
    Out[3]
    3304111941########

    取值成功后,进入For循环的编写。迭代变量设定为i,在case.index范围内进行,逐条取脑卒中患者记录,通过之前的取值程序算出匹配对照的身份证号,写入该患者记录最后一个字段,然后放入case_match中,匹配过的对照按照身份证号从ctrl_里删去。为了调试过程中能看到每一步产出的结果,对temp和aa两个中间变量进行了print。具体代码如下:

    case_match=case.iloc[:0]#建立空匹配库
    for i in case.index:
        temp=case.iloc[i]
        print temp
        aa=ctrl_[(ctrl_.sex==case['sex'].values[i]) & (ctrl_.age==case['age'].values[i]) & (ctrl_.xz==case['xz'].values[i])]['sfzh'].values[0]
        print aa
        temp['ctrl_sfzh']=aa
        case_match=case_match.append(temp,ignore_index=True,sort=False)#拼接匹配完成库
        ctrl_=ctrl_[ctrl_.sfzh !=aa]#删去已匹配对照记录
    

    跑的过程中发现,出现了中断,报错记录显示取到了空值,核实数据库后发现,原来是有脑卒中患者找不到合适的匹配记录。

    Traceback (most recent call last):
      File "D:/work/ʡ����/���?��߹�����Ŀ/2018��ʵ�����������/case_match.py", line 29, in <module>
        aa=ctrl_[(ctrl_.sex==case['sex'].values[i]) & (ctrl_.age==case['age'].values[i]) & (ctrl_.xz==case['xz'].values[i])]['sfzh'].values[0]
    IndexError: index 0 is out of bounds for axis 0 with size 0

    这个坎是绕不过去了,只能求助于try.....except了,try部分里放的是正常的流程,except IndexError表明报错的时候运行以下的程序,把无法匹配的脑卒中患者记录放入另外的一个库case_remain里,问题完美解决!看着一行行print的结果,真是赏心悦目啊。

    case_match=case.iloc[:0]
    case_remain=case.iloc[:0]
    for i in case.index:
        temp=case.iloc[i]
    #     print temp
        try:
            aa=ctrl_[(ctrl_.sex==case['sex'].values[i]) & (ctrl_.age==case['age'].values[i]) & (ctrl_.xz==case['xz'].values[i])]['sfzh'].values[0]
            print aa
            temp['ctrl_sfzh']=aa
            case_match=case_match.append(temp,ignore_index=True,sort=False)
            ctrl_=ctrl_[ctrl_.sfzh !=aa]
        except IndexError:
            case_remain=case_remain.append(temp,ignore_index=True,sort=False)

    有了一次的成功经验后,下一个循环就照猫画虎了,但是要注意数据库命名的时候不要重复了,引用不要出错。

    case_match2=case.iloc[:0]
    case_remain2=case.iloc[:0]
    for i in case_remain.index:
        temp=case_remain.iloc[i]
    #     print temp
        try:
            aa=ctrl_[(ctrl_.sex==case_remain['sex'].values[i]) & (abs(ctrl_.age-case_remain['age'].values[i])<=3) & (ctrl_.xz==case_remain['xz'].values[i])]['sfzh'].values[0]
            print aa
            temp['ctrl_sfzh']=aa
            case_match2=case_match2.append(temp,ignore_index=True,sort=False)
            ctrl_=ctrl_[ctrl_.sfzh !=aa]
        except IndexError:
            case_remain2=case_remain2.append(temp,ignore_index=True,sort=False)

    最后把结果导出到Excel,大功告成!!

    case_match.to_excel(r'D:\case_match.xls')
    case_match2.to_excel(r'D:\case_match2.xls')
    case_remain2.to_excel(r'D:\case_remain2.xls')
    ctrl_.to_excel(r'D:\ctrl_remain.xls')

    总结一下本次编程的体会,搞清楚任务目标后的第一步是熟悉数据库结构,找到关键及核心字段,数据的前期清理也很重要(去重、缺失值的删除/填充);然后是关键及核心字段的取值,先单条再批量,取值结果随时print,这些都是好习惯,不要怕设置中间变量,中间变量多了约容易发现问题,并不是所有人一开始都能写个一长串多重嵌套的代码的,用完的中间变量和调试程序可以用注释语句给标注掉;For循环是个好工具,try....except也能帮你解决好多问题;最后感言一下,“文章不厌百回改,代码不厌百回调”,对于刚入门和生手来说,写代码肯定是个很纠结的过程,会踩各种坑,会碰到各种报错,但解决后程序顺利跑完的成就感是无法言表的。刚开始代码长没关系,结构乱也没关系,只要能跑出需要的结果就行。每当你回头对之前写的代码各种嫌弃的时候,恭喜你的编码能力成长了!最后po整个程序的最终完成版。

    # -*- coding: gbk -*-
    #!/usr/bin/env python
    # __author__ = 'PanJin'
    
    import pandas as pd
    case=pd.read_excel(r'D:\并发症数据库(实验室检测筛选).xls',sheet_name=u'心脑')
    ctrl=pd.read_excel(r'D:\并发症数据库(实验室检测筛选).xls',sheet_name=u'对照(不包含肿瘤)')
    ctrl_=ctrl[(ctrl.sfzh !='3304211932########') & (ctrl.sfzh !='3307221956########') & (ctrl.sfzh !='3304211938########') & (ctrl.sfzh !='3304211939########') & (ctrl.HDLC2 !='#NULL!')]
    # 删除身份证号重复和检查结果缺失的记录
    
    # name=case['name'].values[1]
    # sfzh=case['sfzh'].values[1]
    # sex=case['sex'].values[1]
    # age=case['age'].values[1]
    # xz=case['xz'].values[1]
    # # 取值
    # print name
    # print sfzh
    # print sex
    # print age
    # print xz
    # print ctrl_[(ctrl_.sex==case['sex'].values[0]) & (ctrl_.age==case['age'].values[0]) & (ctrl_.xz==case['xz'].values[0])]['sfzh'].values[0]
    
    case_match=case.iloc[:0]
    case_remain=case.iloc[:0]
    for i in case.index:
        temp=case.iloc[i]
    #     print temp
        try:
            aa=ctrl_[(ctrl_.sex==case['sex'].values[i]) & (ctrl_.age==case['age'].values[i]) & (ctrl_.xz==case['xz'].values[i])]['sfzh'].values[0]
            print aa
            temp['ctrl_sfzh']=aa
            case_match=case_match.append(temp,ignore_index=True,sort=False)
            ctrl_=ctrl_[ctrl_.sfzh !=aa]
        except IndexError:
            case_remain=case_remain.append(temp,ignore_index=True,sort=False)
    
    
    case_match2=case.iloc[:0]
    case_remain2=case.iloc[:0]
    for i in case_remain.index:
        temp=case_remain.iloc[i]
    #     print temp
        try:
            aa=ctrl_[(ctrl_.sex==case_remain['sex'].values[i]) & (abs(ctrl_.age-case_remain['age'].values[i])<=3) & (ctrl_.xz==case_remain['xz'].values[i])]['sfzh'].values[0]
            print aa
            temp['ctrl_sfzh']=aa
            case_match2=case_match2.append(temp,ignore_index=True,sort=False)
            ctrl_=ctrl_[ctrl_.sfzh !=aa]
        except IndexError:
            case_remain2=case_remain2.append(temp,ignore_index=True,sort=False)
    
    case_match.to_excel(r'D:\case_match.xls')
    case_match2.to_excel(r'D:\case_match2.xls')
    case_remain2.to_excel(r'D:\case_remain2.xls')
    ctrl_.to_excel(r'D:\ctrl_remain.xls')
    

     

    转载于:https://my.oschina.net/facewall123/blog/3059514

    展开全文
  • 【R语言】年龄性别频数匹配 挑选样本 病例对照研究,对年龄性别进行频数匹配

    病例对照研究,对年龄性别进行频数匹配

    示例数据

    示例数据下载

    IDgroupsexage
    A1Control90
    A10Control89
    A100Control85
    A1000Control74
    A1001Case74
    A1002Case74
    A1003Case74
    A1004Case74
    A1005Control74
    data <- read.csv("年龄性别频数匹配.csv")
    
    ## 可以先对年龄进行分层处理
    data$agegroup <- cut(data$age,c(0,10,20,30,40,50,60,70,80,90,Inf),
                         right =FALSE # 选取区间开口[ ]情况
                         )
    # 生成list数据,按每一个list[?]为同样sex和age
    dataSplit <- split(data, list(data$sex, data$age))
    
    # 单个list提取
    A <- as.data.frame(data_case[[1]])
    data1 <- A[A$group == "Case", ]
    data2 <- A[A$group == "Control", ]
    num <- as.numeric(table(A$group == "Case")[2])
    set.seed(123) # 设置随机数目,多次重复保持一致
    data3 <- data2[sample(1:NROW(data2), num, replace = FALSE), ]
    assign(paste0("dataFinal", 1), rbind(data1, data3))
    
    # 循环提取
    for (i in 1:length(dataSplit)) {
      A <- as.data.frame(data_case[[i]])
        data1 <- A[A$group == "Case", ]
        data2 <- A[A$group == "Control", ]
        numCase <- nrow(data1)
        numControl <- nrow(data2)
        if (numCase > 0 & numControl>0 & numControl-numCase>=0) {
          na.omit <- TRUE
          set.seed(123) # 设置随机数目,多次重复保持一致 【可以沉默】
          data3 <- data2[sample(1:numControl, numCase, replace = FALSE), ]
          assign(paste0("dataFinal", i), rbind(data1, data3))
        }
        if (numCase > 0 & numControl>0 & numControl-numCase<0) {
          na.omit <- TRUE
          set.seed(123) # 设置随机数目,多次重复保持一致 【可以沉默】
          data3 <- data1[sample(1:numCase, numControl, replace = FALSE), ]
          assign(paste0("dataFinal", i), rbind(data2, data3))
        } 
    }
    
    # 多个数据框合并
    multimerge<-function(dat=list(),...){
      if(length(dat)<2)return(as.data.frame(dat))
      mergedat<-dat[[1]]
      dat[[1]]<-NULL
      for(i in dat){
        mergedat<-merge(all=TRUE,mergedat,i,...)
      }
      return(mergedat)
    }
    
    files=ls(pattern = "dataFinal")
    listALL=list()
    # 数据框合成list
    for (i in 1:length(ls(pattern = "dataFinal"))) {
      eval(parse(text = paste0("listALL","[[",i,"]]", " <- ",files[i])))
    }
    
    dataALL <- multimerge(listALL)
    # 排序
    dataALL=dplyr::arrange(dataALL,age,sex,group)
    # 导出
    write.csv(dataALL,"dataALL.csv",row.names = F)
    
    展开全文
  • 我们可以以相同的方式限制控制单元我们可能会忽略一些或许多原始单位单元组,所有最终匹配的治疗单元以及所有最终匹配对照单元,不应系统地区别,以减少偏差每对中的单位应相似,以减少差异但是,仅评估偏倚部分的...
  • 一个病例对应2个对照等。 MatchIt包帮助文档MatchIt.pdf 1:1匹配也可以参考逆概率加权笔记IPTW 结果分析采用条件logistic回归 #加载包 library(tableone) library(MatchIt) #加载数据 data <- read.csv("测试...

    MatchIt包进行倾向性评分匹配法(Propensity Score Matching, PSM)主要是1:N匹配。一个病例对应2个对照等。

    MatchIt包帮助文档MatchIt.pdf

    1:1匹配也可以参考逆概率加权笔记IPTW

    结果分析采用条件logistic回归

    #加载包
    library(tableone)
    library(MatchIt)
    #加载数据
    data <- read.csv("测试数据.csv")
    names(data)
    #多变量因子化
    data[,4:18]<-lapply(data[,4:18],as.factor)
    #
    matchlist <- matchit(zq101 ~ Sex+Age+bmifz+Education+
              Occupation+Residence+smoke+diabetes+hypertension+tea+
              drink+vegetable+fruit+fish+egg, data=data,
             method   = "nearest",
             distance = "glm",      #
             caliper  = 0.05,       # 卡钳值
             ratio    = 2,          # 1:N 匹配
             replace  = F)          # 不替换
    summary(matchlist)
    # 提取匹配后的病例对照
    matchdata<- match.data(matchlist,
               group = "all",
               distance = "distance",
               weights = "weights",
               subclass = "subclass",
               data = NULL,
               include.s.weights = TRUE,
               drop.unmatched = TRUE)
    table(duplicated(matchdata$id))
    table(matchdata$zq101)
    table(data$zq101)
    
    #排序配对子
    matchdata$subclass <- sort(matchdata$subclass)
    #查看配对子情况,有的病例只有一个对照
    a=table(matchdata$subclass);table(a)
    
    #制作表格
    vars <- c("Age","Sex","bmifz","Education","Occupation","Residence",
              "smoke","drink","tea","diabetes","hypertension",
              "vegetable","fruit","fish","egg" )
    catVars <- c("Sex","bmifz","Education","Occupation","Residence",
                 "smoke","drink","tea","diabetes","hypertension",
                 "vegetable","fruit","fish","egg" )
    nonVars <- c("Age")
    #建立表格
    tabMatched <- CreateTableOne(vars = vars, strata = "zq101", 
                                 factorVars = catVars,
                                 data = matchdata, 
                                 addOverall = TRUE,#添加Overall列的分析结果 
                                 test = TRUE)
    #最终表格
    tab5 <- print(tabMatched, showAllLevels = TRUE, #显示所有水平,不折叠
                  cramVars = catVars, 
                  nonnormal = nonVars, 
                  #exact = "M", 
                  catDigits=2,        #分类变量保留小数位数
                  contDigits=2,       #连续变量保留小数位数
                  quote = FALSE,      #不显示引号 
                  noSpaces = TRUE,    #是否删除为对齐而添加的空间。
                  #如果您希望自己在其他软件中对齐数字,请使用此选项。
                  printToggle = FALSE #输出matrix
    ) 
    tab5
    write.csv(tab5, "Table_One.csv", quote=TRUE, row.names=TRUE) 
    #卡方值看之前卡方循环的笔记
    

    问题:1:2或1:N有的病例只能匹配上一个对照,并不是全部都是一个病例有两个对照与其匹配,测试数据也展现这样的结果。

    是否需要根据配对子把1:1的去掉?然后保留1:2的数据???

    在这里插入图片描述

    展开全文
  • R语言 筛选+匹配

    2022-02-08 15:35:39
    背景:如何匹配向量来筛选,而不是一个一个地使用“或”字符 解决方案:使用%in%替代 library(tidyverse) A <- data.frame(a = 1:5, b = 2:6); A B <- c(2, 4, 5); B # 请问,如何筛选出a == B? filter...
  • 人脸匹配(face matching)

    万次阅读 多人点赞 2019-12-24 14:03:24
    以下是人脸匹配(face matching)的实验报告,实验中采用ldlib,facenet,arcface三种算法,简单对比了三种算法的效果,源代码见文章末尾 一.问题分析 1.问题描述 人脸识别是基于人的脸部特征信息进行身份识别的...
  • 手机型号对照表.xlsx

    2021-02-03 12:24:02
    手机具体型号对比 即程序获取到型号,跟手机的常用名对照。如下 WKG-AN00 华为畅享 20 5G 全网通版 WKG-TN00 华为畅享 20 5G 移动定制版 WLZ-AL10 HUAWEI nova 6 4G 全网通版 WLZ-AN00 HUAWEI nova 6 5G 全网通...
  • HS编码与制造业行业代码对照表,HS2002和HS2007两个版本对照表,其中行业代码与盛斌(2002)保持一致
  • 本资源是身份证号籍贯对照表,记录了全国籍贯对照信息,用于核对身份证信息对应的地址,一般用与查找匹配用,切勿用于非法途径
  • HS编码与制造业行业代码对照表,HS2002和HS2007两个版本对照表,其中行业代码与盛斌(2002)保持一致
  • 采集的数据中,企业注册地址往往都是城市名,如果你想知道这些企业分布的省份,那么就需要这样一张对照表。 文件存储位置: 百度网盘链接: https://pan.baidu.com/s/1T8aobyzXRRvDQ0NjcEBCUw 提取码: cm7g 以下是...
  • 省市中英文对照

    2017-08-17 10:10:16
    省市中英文对照,根据微信地区列表整理
  • 对照匹配时有多个条件如何快速判断与哪个人匹配。我现在有个数据库,要判断100人与这个库哪个人匹配的上,年龄上下三岁,性别一致,接种疫苗时间上下相差14天,
  • 冰箱压缩机与毛细管匹配尺寸参考数据
  • 包含翻译后的API文档:slf4j-api-1.7.25-javadoc-API文档-中文(简体)-英语-对照版.zip 对应Maven信息:groupId:org.slf4j,artifactId:slf4j-api,version:1.7.25 使用方法:解压翻译后的API文档,用浏览器打开...
  • 遥控器型号 配遥控器 遥控器参数 各大品牌杂牌遥控器
  • R语言使用MatchIt包进行倾向性匹配分析(设置匹配方法为nearest,匹配倾向性评分最近的对照组和病例组,1:1配比)、使用match.data函数构建匹配后的样本集合
  • 包含字段、省份、城市名
  • Dsp builder Matlab Quartus 版本匹配
  • 身份证号前六位对应籍贯表大全,可以很方便查出身份证对应的籍贯,方便工作、项目使用
  • 包含翻译后的API文档:spring-security-core-5.3.9.RELEASE-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:org.springframework.security:spring-security-core:5.3.9.RELEASE; 标签:springframework...
  • 统计用区划代码和城乡划分代码,手工整理的,有需要的可以下载,包含三级分类。身份证行政编码对照表.省/直辖市 地级市 县、县级市、区
  • 身份证地址对照码.zip

    2019-12-19 15:40:01
    身份证地址对照码.zip,身份证地址对照码,list,2000年中华人民共和国行政区划代码(截止2000年12月31日),2006年中华人民共和国行政区划代码(截止2006年12月31日),2005年中华人民共和国行政区划代码(截止2005年12...
  • 该工具需要对照样品,该样品可以与患病或肿瘤样品匹配或不匹配。 请参阅tCoNuT Wiki,以获取tCoNuT工作流程的图表。 要求 需要本地安装Perl和R。 R需要在处找到DNAcopy软件包。 validateCNAVariantsVCF.pl需要...
  • 方法:使用世界卫生组织生活质量仪器(WHOQOL-BREF)对18岁及18岁以上成人的代表性样本(病例和对照各100例)进行QOL评估。 还对受访者的社会人口统计学因素进行了评估。 使用Mini International Neuropsychiatric ...
  • 最新最全rabbitmq与erlang版本匹配-2020-04-23
  • 包含2019年全部SCI及SSCI期刊全称缩写对照表(共12185条),可用于文献分析,文献全称或缩写的查找、匹配,excel格式,两列内容全称简介一一对应。(爬虫一条一条爬下来的,感谢支持!)
  • 最小二乘匹配的一个参考程序。本站已有类似程序,但运行结果有问题,提供一个供大家对照
  • 包含翻译后的API文档:springfox-spring-web-3.0.0-javadoc-API文档-中文(简体)-英语-对照版.zip; Maven坐标:io.springfox:springfox-spring-web:3.0.0; 标签:spring、springfox、web、jar包、java、中英对照...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 35,979
精华内容 14,391
关键字:

对照匹配