You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将含双记录类型的固定宽度ASCII仇恨犯罪文件导入R?

导入2021年仇恨犯罪固定宽度文件到R的分步方案

1. 准备字段定义

首先需要获取官方提供的固定宽度字段说明文档,明确BH(Batch Header)和IR(Incident Report)两种记录各自的字段名、起始位置、宽度及数据类型。整理成如下结构的字段定义表:

# BH记录字段定义示例
bh_spec <- tibble::tribble(
  ~col_name, ~start, ~end, ~type,
  "record_type", 1, 2, "character",
  "ori", 3, 9, "character",
  "agency_name", 10, 59, "character",
  # 按实际文档补充剩余BH字段
)

# IR记录字段定义示例
ir_spec <- tibble::tribble(
  ~col_name, ~start, ~end, ~type,
  "record_type", 1, 2, "character",
  "incident_number", 3, 12, "character",
  "offense_date", 13, 20, "date",
  # 按实际文档补充剩余IR字段
)

2. 读取原始文件

用readr::read_lines()读取整份文件的每一行,保留原始行结构以便后续区分记录类型:

library(readr)
raw_lines <- read_lines("2021_hate_crime_master_file.txt")

3. 标记并分组记录

给每行标记记录类型,然后以BH记录为节点生成分组ID,关联对应的IR记录:

library(dplyr)
library(tidyr)

# 转换为数据框并标记记录类型
line_df <- tibble(line = raw_lines) %>%
  mutate(record_type = substr(line, 1, 2))

# 生成BH分组ID:每遇到BH记录,分组ID递增
line_df <- line_df %>%
  mutate(bh_group_id = cumsum(record_type == "BH"))

# 提取BH数据并拆分字段
bh_data <- line_df %>%
  filter(record_type == "BH") %>%
  mutate(across(line, ~str_sub(., bh_spec$start, bh_spec$end))) %>%
  unnest_wider(line, names_sep = "") %>%
  rename_with(~bh_spec$col_name, starts_with("line")) %>%
  select(bh_group_id, everything())

# 提取IR数据并拆分字段
ir_data <- line_df %>%
  filter(record_type == "IR") %>%
  mutate(across(line, ~str_sub(., ir_spec$start, ir_spec$end))) %>%
  unnest_wider(line, names_sep = "") %>%
  rename_with(~ir_spec$col_name, starts_with("line")) %>%
  select(bh_group_id, everything())

4. 生成目标数据结构

选项1:带BH分组的单数据框

通过分组ID左连接BH和IR数据,无事件的BH记录会保留(IR字段为NA):

combined_df <- bh_data %>%
  left_join(ir_data, by = "bh_group_id")

选项2:按ORI分组的多数据框列表

将数据按ORI拆分并存储为命名列表,方便单独查看每个机构的事件数据:

ori_data_list <- combined_df %>%
  group_split(ori) %>%
  set_names(combined_df$ori %>% unique())

# 示例:获取指定ORI的数据
ori_data_list["NY0010000"]

5. 数据类型转换

根据字段定义转换对应的数据类型,比如日期、数值字段:

# 转换BH数据类型示例
bh_data <- bh_data %>%
  mutate(
    total_incidents = as.integer(total_incidents),
    report_date = as.Date(report_date, format = "%Y%m%d")
  )

# 转换IR数据类型示例
ir_data <- ir_data %>%
  mutate(
    offense_date = as.Date(offense_date, format = "%Y%m%d"),
    number_offenses = as.integer(number_offenses)
  )

注意:实际操作需严格匹配官方文档的字段宽度和格式;若遇编码问题,可在read_lines()中添加locale = locale(encoding = "latin1")参数调整。

内容的提问来源于stack exchange,提问作者Kayla Ehman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:15:53