加载 seer 数据到 R
loading seer data into R
我正在尝试从 ASCII 文件加载 SEER 数据。只有一个 .sas 加载文件,我试图将其转换为 R 加载命令。
.sas 加载文件如下所示:
filename seer9 './yr1973_2015.seer9/*.TXT';
data in;
infile seer9 lrecl=362;
input
@ 1 PUBCSNUM $char8. /* Patient ID */
@ 9 REG $char10. /* SEER registry */
@ 19 MAR_STAT $char1. /* Marital status at diagnosis */
@ 20 RACE1V $char2. /* Race/ethnicity */
@ 23 NHIADE $char1. /* NHIA Derived Hisp Origin */
@ 24 SEX $char1. /* Sex */
我有以下代码来尝试复制类似的加载过程:
data <- read.table("OTHER.TXT",
col.names = c("pubcsnum", "reg", "mar_stat", "race1v", "nhaide", "sex"),
sep = c(1, 9, 19, 20, 23, 24))
如果我使用 sep
参数,我会收到以下错误:
Error in read.table("OTHER.TXT", col.names = c("pubcsnum", "reg", "mar_stat",
:invalid 'sep' argument
如果我不使用 sep
参数,我会收到以下错误:
Error in scan(file = file, what = what, sep = sep, quote = quote, dec = dec,
:
line 1 did not have 133 elements
有没有人有加载 seer 数据的经验?有没有人建议为什么这不起作用?
*值得注意的是,当我使用 fill = TRUE
参数时,第二个错误 line 1 did not have 133 elements
不再发生,但是当我评估前几个观察结果时数据不正确。我通过评估一个已知变量进一步确认 sex
:
> summary(data$sex)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000e+00 2.000e+00 3.020e+03 7.852e+18 9.884e+13 2.055e+20
其中值为 1/2,摘要毫无意义
固定宽度的文件,如 .sas 文件所描述的文件,使用 foreign
包中的 read.fwf
函数读取。恐怕普林斯顿主办的格式很好的网页在如何使用 read.table
方面完全错误。实际上没有分隔符,只有位置。在这种情况下,您可以使用(假设您的工作目录中有一个名为 "yr1973_2015.seer9" 的目录):
library(utils) #not really needed, just correcting my faulty memory
inputdf <- read.fwf( "yr1973_2015.seer9/OTHER.TXT",
widths= c(1, 9, 19, 20, 23, 24),
col.names = c("pubcsnum", "reg", "mar_stat", "race1v", "nhaide", "sex"))
你会丢失大部分信息,因为 lrecl
值告诉我们每行有 362 个字符,但这将是一个很好的测试用例,然后你可以切换到 SAScii 函数....感谢@AnthonyDamico:
packageDescription("SAScii")
#---------------
Package: SAScii
Type: Package
Title: Import ASCII files directly into R using only a SAS
input script
Version: 1.0
Date: 2012-08-18
Authors@R: person( "Anthony Joseph" , "Damico" , role = c(
"aut" , "cre" ) , email = "ajdamico@gmail.com" )
Description: Using any importation code designed for SAS
users to read ASCII files into sas7bdat files, the
SAScii package parses through the INPUT block of a
(.sas) syntax file to design the parameters needed
for a read.fwf function call. This allows the user
to specify the location of the ASCII (often a .dat)
file and the location of the .sas syntax file, and
then load the data frame directly into R in just one
step.
License: GPL (>= 2)
URL: https://github.com/ajdamico/SAScii
Depends: R (>= 2.14)
LazyLoad: Yes
Packaged: 2012-08-17 08:35:18 UTC; AnthonyD
Author: Anthony Joseph Damico [aut, cre]
Maintainer: Anthony Joseph Damico <ajdamico@gmail.com>
Repository: CRAN
Date/Publication: 2012-08-17 10:55:15
Built: R 3.4.0; ; 2017-04-20 18:55:31 UTC; unix
-- File: /Library/Frameworks/R.framework/Versions/3.4/Resources/library/SAScii/Meta/package.rds
我不确定那些长行中的尾随信息是否会被有效地忽略,但通过 ?read.fwf
页面上第一个示例的这个轻微 mod 进行了检查:
> ff <- tempfile()
> cat(file = ff, "12345689", "98765489", sep = "\n")
> read.fwf(ff, widths = c(1,2,3))
V1 V2 V3
1 1 23 456
2 9 87 654
>unlink(ff)
我检查了我的记忆,使用 Anthony 的名字作为搜索词可能会有帮助,并且发现他的网站已经更新。查看:
http://asdfree.com/surveillance-epidemiology-and-end-results-seer.html
所以其他评论和答案指出了大部分内容,但这里有一个更完整的答案来解决您的确切问题。我听说很多人都在为这些 ASCII 文件(包括许多相关但不是很简单的包)而苦苦挣扎,我想为其他搜索的人回答这些问题。
固定宽度文件
这些 SEER "ASCII" 文件实际上是固定宽度的文本文件(ASCII 是编码标准而不是文件格式)。这意味着没有分隔字段(在 .csv 或 .tsv 中)的分隔符(例如“,”或“\t”)。
相反,每个字段由行中的开始和结束位置定义(有时是开始位置和字段 width/length)。这是我们看到的.sas文件中你总结的:
input
@ 1 PUBCSNUM $char8. /* Patient ID */
@ 9 REG $char10. /* SEER registry */
...
这是什么意思?
- 第一个患者 ID 字段从位置 1 开始,长度为 8(来自 $char8,类似于 SQL 模式等),这意味着它在位置 8 处结束。
- 第二个字段,SEER 注册表 ID,从位置 9(前一个字段的 1 + 8)开始,长度为 10(同样来自$char10)这意味着它在位置18.
处结束
- 等
其中 @
数字持续增加,因此字段不会重叠。
读取固定宽度的文件
我发现 readr::read_fwf()
函数既好又简单,主要是因为它有几个辅助函数,即 fwf_positions()
告诉它如何通过开始和结束(或宽度, fwf_widths()
)。
因此,要从文件中读取这两个字段,我们可以这样做:
read_fwf(<file>, fwf_positions(start=c(1, 9), end=c(8, 18), col_names=c("patient_id", "registry_id")))
其中 col_names 仅用于重命名列。
帮助脚本。
我之前一直在努力解决这些问题,所以我实际上写了 some code 来读取该 .sas 文件并提取起始位置、宽度、列名和描述。
这是全部内容,只需替换文件名:
## Script to read the SEER file dictionary and use it to read SEER ASCII data files.
library(tidyverse)
library(stringr)
#### Reading the file dictionary ----
## https://seer.cancer.gov/manuals/read.seer.research.nov2017.sas
sas.raw <- read_lines("https://seer.cancer.gov/manuals/read.seer.research.nov2017.sas")
sas.df <- tibble(raw = sas.raw) %>%
## remove first few rows by insisting an @ that defines the start index of that field
filter(str_detect(raw, "@")) %>%
## extract out the start, width and column name+description fields
mutate(start = str_replace(str_extract(raw, "@ [[:digit:]]{1,3}"), "@ ", ""),
width = str_replace(str_extract(raw, "\$char[[:digit:]]{1,2}"), "\$char", ""),
col_name = str_extract(raw, "[[:upper:]]+[[:upper:][:digit:][:punct:]]+"),
col_desc = str_trim(str_replace(str_replace(str_extract(raw, "\/\*.+\*\/"), "\/\*", ""), "\*\/", "" )) ) %>%
## coerce to integers
mutate_at(vars(start, width), funs(as.integer)) %>%
## calculate the end position
mutate(end = start + width - 1)
column_mapping <- sas.df %>%
select(col_name, col_desc)
#### read the file with the start+end positions----
## CHANGE THIS LINE
file_path = "data/test_COLRECT.txt"
## read the file with the fixed width positions
data.df <- read_fwf(file_path,
fwf_positions(sas.df$start, sas.df$end, sas.df$col_name))
## result is a tibble
希望对您有所帮助!
我正在尝试从 ASCII 文件加载 SEER 数据。只有一个 .sas 加载文件,我试图将其转换为 R 加载命令。
.sas 加载文件如下所示:
filename seer9 './yr1973_2015.seer9/*.TXT';
data in;
infile seer9 lrecl=362;
input
@ 1 PUBCSNUM $char8. /* Patient ID */
@ 9 REG $char10. /* SEER registry */
@ 19 MAR_STAT $char1. /* Marital status at diagnosis */
@ 20 RACE1V $char2. /* Race/ethnicity */
@ 23 NHIADE $char1. /* NHIA Derived Hisp Origin */
@ 24 SEX $char1. /* Sex */
我有以下代码来尝试复制类似的加载过程:
data <- read.table("OTHER.TXT",
col.names = c("pubcsnum", "reg", "mar_stat", "race1v", "nhaide", "sex"),
sep = c(1, 9, 19, 20, 23, 24))
如果我使用 sep
参数,我会收到以下错误:
Error in read.table("OTHER.TXT", col.names = c("pubcsnum", "reg", "mar_stat",
:invalid 'sep' argument
如果我不使用 sep
参数,我会收到以下错误:
Error in scan(file = file, what = what, sep = sep, quote = quote, dec = dec,
:
line 1 did not have 133 elements
有没有人有加载 seer 数据的经验?有没有人建议为什么这不起作用?
*值得注意的是,当我使用 fill = TRUE
参数时,第二个错误 line 1 did not have 133 elements
不再发生,但是当我评估前几个观察结果时数据不正确。我通过评估一个已知变量进一步确认 sex
:
> summary(data$sex)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.000e+00 2.000e+00 3.020e+03 7.852e+18 9.884e+13 2.055e+20
其中值为 1/2,摘要毫无意义
固定宽度的文件,如 .sas 文件所描述的文件,使用 foreign
包中的 read.fwf
函数读取。恐怕普林斯顿主办的格式很好的网页在如何使用 read.table
方面完全错误。实际上没有分隔符,只有位置。在这种情况下,您可以使用(假设您的工作目录中有一个名为 "yr1973_2015.seer9" 的目录):
library(utils) #not really needed, just correcting my faulty memory
inputdf <- read.fwf( "yr1973_2015.seer9/OTHER.TXT",
widths= c(1, 9, 19, 20, 23, 24),
col.names = c("pubcsnum", "reg", "mar_stat", "race1v", "nhaide", "sex"))
你会丢失大部分信息,因为 lrecl
值告诉我们每行有 362 个字符,但这将是一个很好的测试用例,然后你可以切换到 SAScii 函数....感谢@AnthonyDamico:
packageDescription("SAScii")
#---------------
Package: SAScii
Type: Package
Title: Import ASCII files directly into R using only a SAS
input script
Version: 1.0
Date: 2012-08-18
Authors@R: person( "Anthony Joseph" , "Damico" , role = c(
"aut" , "cre" ) , email = "ajdamico@gmail.com" )
Description: Using any importation code designed for SAS
users to read ASCII files into sas7bdat files, the
SAScii package parses through the INPUT block of a
(.sas) syntax file to design the parameters needed
for a read.fwf function call. This allows the user
to specify the location of the ASCII (often a .dat)
file and the location of the .sas syntax file, and
then load the data frame directly into R in just one
step.
License: GPL (>= 2)
URL: https://github.com/ajdamico/SAScii
Depends: R (>= 2.14)
LazyLoad: Yes
Packaged: 2012-08-17 08:35:18 UTC; AnthonyD
Author: Anthony Joseph Damico [aut, cre]
Maintainer: Anthony Joseph Damico <ajdamico@gmail.com>
Repository: CRAN
Date/Publication: 2012-08-17 10:55:15
Built: R 3.4.0; ; 2017-04-20 18:55:31 UTC; unix
-- File: /Library/Frameworks/R.framework/Versions/3.4/Resources/library/SAScii/Meta/package.rds
我不确定那些长行中的尾随信息是否会被有效地忽略,但通过 ?read.fwf
页面上第一个示例的这个轻微 mod 进行了检查:
> ff <- tempfile()
> cat(file = ff, "12345689", "98765489", sep = "\n")
> read.fwf(ff, widths = c(1,2,3))
V1 V2 V3
1 1 23 456
2 9 87 654
>unlink(ff)
我检查了我的记忆,使用 Anthony 的名字作为搜索词可能会有帮助,并且发现他的网站已经更新。查看:
http://asdfree.com/surveillance-epidemiology-and-end-results-seer.html
所以其他评论和答案指出了大部分内容,但这里有一个更完整的答案来解决您的确切问题。我听说很多人都在为这些 ASCII 文件(包括许多相关但不是很简单的包)而苦苦挣扎,我想为其他搜索的人回答这些问题。
固定宽度文件
这些 SEER "ASCII" 文件实际上是固定宽度的文本文件(ASCII 是编码标准而不是文件格式)。这意味着没有分隔字段(在 .csv 或 .tsv 中)的分隔符(例如“,”或“\t”)。
相反,每个字段由行中的开始和结束位置定义(有时是开始位置和字段 width/length)。这是我们看到的.sas文件中你总结的:
input
@ 1 PUBCSNUM $char8. /* Patient ID */
@ 9 REG $char10. /* SEER registry */
...
这是什么意思?
- 第一个患者 ID 字段从位置 1 开始,长度为 8(来自 $char8,类似于 SQL 模式等),这意味着它在位置 8 处结束。
- 第二个字段,SEER 注册表 ID,从位置 9(前一个字段的 1 + 8)开始,长度为 10(同样来自$char10)这意味着它在位置18. 处结束
- 等
其中 @
数字持续增加,因此字段不会重叠。
读取固定宽度的文件
我发现 readr::read_fwf()
函数既好又简单,主要是因为它有几个辅助函数,即 fwf_positions()
告诉它如何通过开始和结束(或宽度, fwf_widths()
)。
因此,要从文件中读取这两个字段,我们可以这样做:
read_fwf(<file>, fwf_positions(start=c(1, 9), end=c(8, 18), col_names=c("patient_id", "registry_id")))
其中 col_names 仅用于重命名列。
帮助脚本。
我之前一直在努力解决这些问题,所以我实际上写了 some code 来读取该 .sas 文件并提取起始位置、宽度、列名和描述。
这是全部内容,只需替换文件名:
## Script to read the SEER file dictionary and use it to read SEER ASCII data files.
library(tidyverse)
library(stringr)
#### Reading the file dictionary ----
## https://seer.cancer.gov/manuals/read.seer.research.nov2017.sas
sas.raw <- read_lines("https://seer.cancer.gov/manuals/read.seer.research.nov2017.sas")
sas.df <- tibble(raw = sas.raw) %>%
## remove first few rows by insisting an @ that defines the start index of that field
filter(str_detect(raw, "@")) %>%
## extract out the start, width and column name+description fields
mutate(start = str_replace(str_extract(raw, "@ [[:digit:]]{1,3}"), "@ ", ""),
width = str_replace(str_extract(raw, "\$char[[:digit:]]{1,2}"), "\$char", ""),
col_name = str_extract(raw, "[[:upper:]]+[[:upper:][:digit:][:punct:]]+"),
col_desc = str_trim(str_replace(str_replace(str_extract(raw, "\/\*.+\*\/"), "\/\*", ""), "\*\/", "" )) ) %>%
## coerce to integers
mutate_at(vars(start, width), funs(as.integer)) %>%
## calculate the end position
mutate(end = start + width - 1)
column_mapping <- sas.df %>%
select(col_name, col_desc)
#### read the file with the start+end positions----
## CHANGE THIS LINE
file_path = "data/test_COLRECT.txt"
## read the file with the fixed width positions
data.df <- read_fwf(file_path,
fwf_positions(sas.df$start, sas.df$end, sas.df$col_name))
## result is a tibble
希望对您有所帮助!