загрузка данных провидца в R - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь загрузить данные SEER из файлов ASCII. Есть только файл загрузки .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

У кого-нибудь есть опыт загрузки данных провидца? У кого-нибудь есть предложение, почему это не работает?

Замечание

*, когда я использую аргумент 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, а сводка не имеет смысла

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Так что другие комментарии и ответы указывают на большую часть этого, но вот более полный ответ для вашей конкретной проблемы. Я слышал о многих людях, борющихся с этими файлами ASCII (включая многие связанные, но не очень простые пакеты), и я хотел ответить на них всем, кто ищет.

Файлы фиксированной ширины

Эти файлы SEER "ASCII" на самом деле являются текстовыми файлами фиксированной ширины (ASCII - это стандарт кодирования, а не формат файла). Это означает, что нет символа разделителя (например, "," или "\ t"), который разделяет поля (в .csv или .tsv).

Вместо этого каждое поле определяется начальной и конечной позицией в строке (иногда начальной позицией и шириной / длиной поля). Вот что мы видим в файле .sas, который вы суммируете:

input                                                                               
@ 1   PUBCSNUM             $char8.  /* Patient ID */                              
@ 9   REG                  $char10. /* SEER registry */  
...

Что это значит?

  • первое поле идентификатора пациента начинается с позиции 1 и имеет длину 8 (от $ char8, аналогично точности в схемах SQL и т. Д.), Что означает, что оно заканчивается в позиции 8 .
  • второе поле, идентификатор реестра SEER, начинается с позиции 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 только для переименования столбцов.

Вспомогательный скрипт.

Я боролся с этим прежде, поэтому я на самом деле написал некоторый код , который читает этот файл .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

Надеюсь, это поможет!

0 голосов
/ 01 мая 2018

Файлы фиксированной ширины, например, описанные в этом файле .sas, читаются с помощью функции read.fwf в пакете foreign. Я боюсь, что красиво отформатированная веб-страница, размещенная Принстоном, просто неверна в том, как использовать 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:

> 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)

Я проверил свою память, что использование имени Энтони в качестве поискового запроса может быть полезным, и обнаружил, что его веб-сайт был обновлен. Проверить:

http://asdfree.com/surveillance-epidemiology-and-end-results-seer.html

...