使用 Cloud Healthcare API 对 FHIR 临床数据进行去标识化


本教程面向与医疗保健和生命科学组织合作的研究人员、数据科学家和 IT 团队,介绍如何使用快速医疗互操作性资源 (FHIR)Cloud Healthcare API 进行去标识化操作来移除或修改 FHIR 临床数据中的个人身份信息 (PII),包括受保护健康信息 (PHI)。对医疗数据进行去标识化处理有助于保护患者隐私,并且有助于准备医疗保健数据以便用于研究、数据共享和机器学习。

本教程假定您具备 Linux 基本知识。对 Google Cloud 和 FHIR 规范及其在电子健康记录系统 (EHR) 中的使用情况有基本的了解也会很有帮助。本教程中的所有命令均在 Cloud Shell 中运行。

目标

  • 创建 Cloud Healthcare API 数据集FHIR 存储区
  • 将 FHIR 数据导入 Cloud Healthcare API FHIR 存储区。
  • 使用 Cloud Healthcare API 的 FHIR 去标识化操作来移除或修改 FHIR 存储区中 FHIR 实例中的 PII 和 PHI。
  • 使用 curl 命令行工具,通过 Cloud Healthcare API 进行 FHIR 去标识化调用。

费用

本教程使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用量来估算费用。

准备工作

所有 Cloud Healthcare API 的使用都在 Google Cloud 项目的上下文中进行。项目是执行下列操作的基础:创建、启用和使用所有 Google Cloud 服务,包括管理 API、启用结算功能、添加和移除协作者以及管理 Google Cloud 资源的权限。使用以下过程创建 Google Cloud 项目,或者选择您已创建的项目。

  1. In the Google Cloud console, go to the project selector page.

    Go to project selector

  2. Select or create a Google Cloud project.

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Cloud Healthcare API.

    Enable the API

  5. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  6. 在 Cloud Shell 中,运行 gcloud components update 命令以确保您拥有最新版本的 gcloud CLI,其中包含与 Cloud Healthcare API 相关的功能。

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

创建 IAM 服务账号

本教程需要 Healthcare Dataset Administrator、FHIR Administrator 和 FHIR Resource Editor 角色。使用以下步骤创建服务账号并分配正确的角色:

  1. 创建服务账号
  2. 为服务账号分配角色:

    • Healthcare Dataset Administrator
    • Healthcare FHIR Administrator
    • Healthcare FHIR Resource Editor
  3. 创建并下载服务账号 JSON 密钥

  4. 激活您的服务账号密钥:

    gcloud auth activate-service-account --key-file=path-to-key-file
    

    输出如下所示:

    Activated service account credentials for: [key-name@project-name.iam.gserviceaccount.com]
    
    • key-name 是您分配给服务账号密钥的名称。
    • project-name 是您的 Google Cloud 项目的名称。

获取 OAuth 2.0 访问令牌

如需使用 Cloud Healthcare API 提取数据,您需要本教程中的命令为您获取的 OAuth 2.0 访问令牌。在本教程中,一些示例 Cloud Healthcare API 请求将使用 curl 命令行工具。这些示例使用 gcloud auth print-access-token 命令获取 OAuth 2.0 不记名令牌,以及将该令牌包含在请求的授权标头中。如需详细了解此命令,请参阅 gcloud auth application-default print-access-token

设置用于去标识化的 FHIR 数据集

每个 FHIR 资源都是一个类似 JSON 的对象,包含键值对。一些元素是标准化的,而其他元素则是自由文本。您可以使用去标识化操作执行以下操作:

  • 移除 FHIR 资源中特定键对应的值。
  • 处理非结构化文本以仅移除 PII 元素,而将其余文本内容保持原样。

对数据集进行去标识化处理时,在发出去标识化 API 调用之前不能存在目标数据集。去标识化操作会创建目标数据集。

对单个 FHIR 存储区进行去标识化处理时,在发出去标识化 API 调用之前必须存在目标数据集。

源数据集、FHIR 存储区和目标数据集的 FHIR 存储区必须位于同一 Google Cloud 项目中。当您运行去标识化操作时,系统会在源数据集和 FHIR 存储区所在的 Google Cloud 项目中创建目标数据集和 FHIR 存储区。

如果要生成本教程适用的合成 FHIR 数据,您可以使用 Synthea 生成 FHIR STU3 格式的合成数据,将生成的数据复制到 Cloud Storage 存储桶,然后将其导入 Cloud Healthcare API FHIR 存储区。Synthea 不会生成包含自由或非结构化文本组件的 FHIR 数据,因此您无法使用它来探索去标识化的这些方面。

在本教程中,您将按照以下过程将示例 FHIR 数据导入 FHIR 存储区。

  1. 为将要存储数据集、FHIR 存储区和 FHIR 数据的项目和位置设置环境变量。分配给环境变量的值是示例值,如下所示:

    export PROJECT_ID=MyProj
    export REGION=us-central1
    export SOURCE_DATASET_ID=dataset1
    export FHIR_STORE_ID=FHIRstore1
    export DESTINATION_DATASET_ID=deid-dataset1
    

    在上面的示例中声明的环境变量定义如下所示:

    • $PROJECT_ID 是您的 Google Cloud 项目标识符。
    • $REGION 是创建 Cloud Healthcare API 数据集的 Google Cloud 地区。
    • $SOURCE_DATASET_ID 是存储源数据的 Cloud Healthcare API 数据集的名称。
    • $FHIR_STORE_ID 是源 Cloud Healthcare API FHIR 存储区的名称。
    • $DESTINATION_DATASET_ID 是其中写入了去标识化数据的 Cloud Healthcare API 目标数据集的名称。

    您将在本教程的稍后部分使用这些环境变量。

  2. 创建 Cloud Healthcare API 数据集:

    gcloud healthcare datasets create $SOURCE_DATASET_ID --location=$REGION
    

    输出类似于以下内容,其中 [OPERATION_NUMBER] 是用于跟踪请求的数据集创建操作标识符:

    Create request issued for: $SOURCE_DATASET_ID
    
    Waiting for operation [OPERATION_NUMBER] to complete...done.
    Created dataset $SOURCE_DATASET_ID.
    

    上述命令会在地区 $REGION 中创建名为 $SOURCE_DATASET_ID 的源数据集。

  3. 使用以下命令创建 FHIR 存储区:

    gcloud healthcare fhir-stores create $FHIR_STORE_ID \
        --dataset=$SOURCE_DATASET_ID --location=$REGION
    

    上述命令会在数据集 $SOURCE_DATASET_ID 中创建一个名为 $FHIR_STORE_ID 的 FHIR 存储区。

  4. 通过以下命令,使用 FHIR create 函数将 FHIR 患者资源添加到 FHIR 存储区中:

    curl -X POST \
        -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -H "Content-Type: application/fhir+json; charset=utf-8" \
        --data "{
           \"address\": [
        {
          \"city\": \"Anycity\",
          \"district\": \"Anydistrict\",
          \"line\": [
            \"123 Main Street\"
          ],
          \"period\": {
            \"start\": \"1990-12-05\"
          },
          \"postalCode\": \"12345\",
          \"state\": \"CA\",
          \"text\": \"123 Main Street Anycity, Anydistrict, CA 12345\",
          \"use\": \"home\"
        }
      ],
              \"name\": [
            {
              \"family\": \"Smith\",
              \"given\": [
                \"Darcy\"
              ],
              \"use\": \"official\"
            }
          ],
          \"gender\": \"female\",
          \"birthDate\": \"1980-12-05\",
          \"resourceType\": \"Patient\"
        }" \
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/fhirStores/$FHIR_STORE_ID/fhir/Patient"
    

    该命令的参数对应于示例 FHIR 资源(即 FHIR 患者资源)。

    {
      "address": [
        {
          "city": "Anycity",
          "district": "Anydistrict",
          "line": [
            "123 Main Street"
          ],
          "period": {
            "start": "1990-12-05"
          },
          "postalCode": "12345",
          "state": "CA",
          "text": "123 Main Street Anycity, Anydistrict, CA 12345",
          "use": "home"
        }
      ],
      "name": [
        {
          "family": "Smith",
          "given": [
            "Darcy"
          ],
    "use": "official"
        }
      ],
    "gender": "female",
    "birthDate": "1980-12-05",
     "resourceType": "Patient"
    }
    

    如果请求成功,则服务器会返回如下所示的输出:

    {
      "address": [
        {
          "city": "Anycity",
          "district": "Anydistrict",
          "line": [
            "123 Main Street"
          ],
          "period": {
            "start": "1990-12-05"
          },
          "postalCode": "12345",
          "state": "CA",
          "text": "123 Main Street Anycity, Anydistrict, CA 12345",
          "use": "home"
        }
      ],
      "birthDate": "1980-12-05",
      "gender": "female",
      "id": "0359c226-5d63-4845-bd55-74063535e4ef",
      "meta": {
        "lastUpdated": "2020-02-08T00:03:21.745220+00:00",
        "versionId": "MTU4MTEyMDIwMTc0NTIyMDAwMA"
      },
      "name": [
        {
          "family": "Smith",
          "given": [
            "Darcy"
          ],
          "use": "official"
        }
      ],
      "resourceType": "Patient"
    }
    

    上面的 curl 命令会在源 FHIR 存储区中插入新的患者资源。系统会在输出中生成一个患者标识符 (id)。患者标识符是去标识化的字母数字字符串,它在 FHIR 相遇资源中用来与 FHIR 患者资源关联。

  5. 通过以下命令,使用 FHIR create 函数将 FHIR 相遇资源添加到 FHIR 存储区中。在该命令中,将 subject.reference 值替换为上述 curl 命令的输出中的患者标识符值:

    curl -X POST \
        -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -H "Content-Type: application/fhir+json; charset=utf-8" \
        --data "{
          \"status\": \"finished\",
          \"class\": {
            \"system\": \"http://hl7.org/fhir/v3/ActCode\",
            \"code\": \"IMP\",
            \"display\": \"inpatient encounter\"
          },
          \"reason\": [
            {
              \"text\": \"Mrs. Smith is a 39-year-old female who has a past
    medical history significant for a myocardial infarction. Catheterization
    showed a possible kink in one of her blood vessels.\"
            }
          ],
          \"subject\": {
            \"reference\":
    \"Patient/0359c226-5d63-4845-bd55-74063535e4ef\"
          },
          \"resourceType\": \"Encounter\"
        }" \
    
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/fhirStores/$FHIR_STORE_ID/fhir/Encounter"
    

    该命令的参数对应于示例 FHIR 资源(即 FHIR 相遇资源):

    {
          "status": "finished",
          "class": {
            "system": "http://hl7.org/fhir/v3/ActCode",
            "code": "IMP",
            "display": "inpatient encounter"
          },
          "reason": [
            {
              "text": "Mrs. Smith is a 39-year-old female who has a past medical
    history significant for a myocardial infarction. Catheterization showed a
    possible kink in one of her blood vessels."
            }
          ],
          "subject": {
            "reference": "Patient/0359c226-5d63-4845-bd55-74063535e4ef"
          },
          "resourceType": "Encounter"
        }
    

    如果请求成功,则服务器会返回如下所示的输出:

    {
      "class": {
        "code": "IMP",
        "display": "inpatient encounter",
        "system": "http://hl7.org/fhir/v3/ActCode"
      },
      "id": "0038a95f-3c11-4163-8c2e-10842b6b1547",
      "meta": {
        "lastUpdated": "2020-02-12T00:39:16.822443+00:00",
        "versionId": "MTU4MTQ2Nzk1NjgyMjQ0MzAwMA"
      },
      "reason": [
        {
          "text": "Mrs. Smith is a 39-year-old female who has a past medical history
    significant for a myocardial infarction. Catheterization showed a possible
    kink in one of her blood vessels."
        }
      ],
      "resourceType": "Encounter",
      "status": "finished",
      "subject": {
        "reference": "Patient/0359c226-5d63-4845-bd55-74063535e4ef"
      }
    

    上面的 curl 命令会在源 FHIR 存储区中插入新的相遇资源。

对 FHIR 数据进行去标识化

接下来,您需要对源 FHIR 存储区中插入的 FHIR 数据进行去标识化处理。您可以遮盖或转换结构化字段(例如 Patient.namePatient.address 字段)中的所有 PII 元素。此外,您还需要对非结构化文本数据(例如 Encounter.reason.text)中的 PII 元素进行去标识化处理。

然后,您可以选择性地将生成的数据直接导出到 BigQuery 以供分析和机器学习训练。

去标识化的此配置可用于群体健康分析或类似的使用场景。在本教程的上下文中,您可以将去标识化的结构化数据迁移到 BigQuery 以评估大规模趋势。您可能不需要非结构化字段,这些字段很难大规模地进行规范化和分析。但是,本教程包含非结构化字段作为参考。

您可以在多种使用场景中对 FHIR 数据进行去标识化处理。Cloud Healthcare API 还支持多种配置选项。如需了解详情(包括示例 curl 命令以及不同场景的 Tools for PowerShell 示例),请参阅对 FHIR 数据进行去标识化处理

包含日期的字段通过日期偏移技术进行转换,以便将 FHIR 资源中的所有日期偏移一段一致的随机时间。日期偏移在 FHIR 资源中保持一致,以便保留与医疗相关的详细信息(例如患者年龄和预约间隔时间),并且不会泄露与患者有关的身份信息。非结构化字段中的所有标识符也会进行转换。

以下示例还包括对 name 字段进行的哈希转换。哈希是一种单向加密技术,用于确保名称始终转换为相同的输出值,从而在数据集中针对跨多条记录的同一患者姓名生成一致的输出。在此操作中,您将遮盖 PII,同时保留资源之间的关联。

在本示例中,所提供的加密密钥 U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU= 是使用以下命令生成的 AES 加密 256 位 base64 编码密钥。

echo -n "test" | openssl enc -e -aes-256-ofb -a -salt

该命令会要求您输入密码。输入您选择的密码。

  1. 使用 curl 命令遮盖或转换结构化字段(如 nameaddress 字段)中的所有 PII 元素,以及转换非结构化字段中的所有标识符。

    curl -X POST \
        -H "Authorization: Bearer "$(gcloud auth print-access-token) \
        -H "Content-Type: application/json; charset=utf-8" \
        --data "{
          'destinationDataset':
    'projects/$PROJECT_ID/locations/$REGION/datasets/$DESTINATION_DATASET_ID',
          'config': {
          'fhir': {
              'fieldMetadataList': {
                'paths': [
                  'Patient.address.state',
                  'Patient.address.line',
                  'Patient.address.text',
                  'Patient.address.postalCode'
                ],
                'action': 'TRANSFORM'
              },
             'fieldMetadataList': {
               'paths': [
                 'Encounter.reason.text'
               ],
               'action': 'INSPECT_AND_TRANSFORM'
             },
           'text': {
             'transformations': [
               {
                 'infoTypes': [],
                 'replaceWithInfoTypeConfig': {}
               }
             ]
           },
              'fieldMetadataList': {
                'paths': [
                  'Patient.name.family',
                  'Patient.name.given'
                ],
                'action': 'TRANSFORM'
              },
            'text': {
              'transformations': {
                'infoTypes': [
                  'PERSON_NAME'
                ],
                'cryptoHashConfig': {
                  'cryptoKey':
    'U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU='
                }
              }
            },
              'fieldMetadataList': {
                'paths': [
                  'Patient.birthDate',
                  'Patient.address.period.start'
                ],
                'action': 'TRANSFORM'
              },
            'text': {
              'transformations': {
                'infoTypes': [
                  'DATE'
                ],
                'dateShiftConfig': {
                  'cryptoKey':
    'U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU='
                }
              }
            }
          }
        }"
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID:deidentify"
    

    如果请求成功,则服务器会返回 JSON 格式的响应,如下所示:

    {
      "name": "projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/OPERATION_NAME"
    }
    

    在上面的示例中,curl 命令通过以下方式转换值以对 FHIR 资源进行去标识化:

    • 遮盖 Patient.address.line 值、Patient.address.text 值和 Patient.address.postalCode 值。
    • Patient.name.family 值和 Patient.name.given 值替换为哈希值。
    • Patient.birthDate 字段和 period.start 字段中的值替换为日期偏移技术(其差值为 100 天)生成的值。
    • Encounter.reason.text 字段中,将患者的姓氏替换为哈希值,并将患者的年龄替换为字面量值 [AGE]
  2. 对上述操作的响应中将包含操作名称。使用 get 方法来跟踪操作的状态:

    curl -X GET \
        -H "Authorization: Bearer "$(gcloud auth print-access-token) \
        -H "Content-Type: application/json; charset=utf-8" \
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/operations/OPERATION_NAME"
    

    如果请求成功,则服务器会返回 JSON 格式的响应。去标识化过程完成后,响应会包含 "done": true

    {
      "name": "projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/operations/OPERATION_NAME",
      "metadata": {
        "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
        "apiMethodName": "google.cloud.healthcare.v1.dataset.DatasetService.DeidentifyDataset",
        "createTime": "2018-01-01T00:00:00Z",
        "endTime": "2018-01-01T00:00:00Z"
      },
      "done": true,
      "response": {
        "@type": "...",
        "successStoreCount": "SUCCESS_STORE_COUNT"
      }
    }
    

    上述命令将返回去标识化操作的状态。

  3. 通过运行以下命令,使用患者标识符获取新目标数据集中的 FHIR 患者资源详细信息:

    curl -X GET \
         -H "Authorization: Bearer $(gcloud auth print-access-token)" \
     "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$DESTINATION_DATASET_ID/fhirStores/$FHIR_STORE_ID/fhir/Patient/a952e409-2403-43e6-9815-cb78c5b5eca2/\$everything"
    

    如果请求成功,服务器将返回如下所示的响应,即原始 FHIR 资源的去标识化版本:

      "entry": [\
        {\
          "resource": {\
            "class": {\
              "code": "IMP",\
              "display": "inpatient encounter",\
              "system": "http://hl7.org/fhir/v3/ActCode"\
            },\
            "id": "0038a95f-3c11-4163-8c2e-10842b6b1547",\
            "reason": [\
              {\
                "text": "Mr. NlVBV12Hhb5DD8WNqlTpXboFxzlUSlqAmYDet/jIViQ= is a [AGE]
    gentleman who has a past medical history significant for a myocardial
    infarction. Catheterization showed a possible kink in one of his vessels."\
              }\
            ],\
            "resourceType": "Encounter",\
            "status": "finished",\
            "subject": {\
              "reference": "Patient/0359c226-5d63-4845-bd55-74063535e4ef"\
            }\
          }\
        },\
        {\
          "resource": {\
            "address": [\
              {\
                "city": "Anycity",\
                "district": "Anydistrict",\
                "line": [\
                  ""\
                ],\
                "period": {\
                  "start": "1990-09-23"\
                },\
                "postalCode": "",\
                "state": "",\
                "text": "",\
                "use": "home"\
              }\
            ],\
            "birthDate": "1980-09-23",\
            "gender": "female",\
            "id": "0359c226-5d63-4845-bd55-74063535e4ef",\
            "name": [\
              {\
                "family": "NlVBV12Hhb5DD8WNqlTpXboFxzlUSlqAmYDet/jIViQ=",\
                "given": [\
                  "FSH4e the project.D/IGb80a1rS0L0kqfC3DCDt6//17VPhIkOzH2pk="\
                ],\
                "use": "official"\
              }\
            ],\
            "resourceType": "Patient"\
          }\
        }\
      ],\
      "resourceType": "Bundle",\
      "total": 2,\
      "type": "searchset"\
    }
    

    上述命令可验证是否已通过去标识化操作成功对 FHIR 资源进行去标识化处理。

清理

为避免因本教程中使用的资源导致您的 Google Cloud 账号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除项目

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

逐个删除资源

  • 删除目标数据集:

    gcloud healthcare datasets delete $DESTINATION_DATASET_ID
    

后续步骤