Проблема
Я извлек несколько таблиц из URL-адресов и объединил их. Каждый URL-адрес представляет собой идентификатор. Объединенный фрейм данных структурирован неправильно, поскольку форматы таблиц различаются между идентификаторами.
Примеры структур таблиц:
https://www.sec.gov/Archives/edgar/data/1000097/0000919574-13-001835.txt # Использует "," как разделитель тысяч https://www.sec.gov/Archives/edgar/data/1001085/0001193125-13-060806.txt # Не использует разделитель тысяч
Код
Код, используемый для извлечения таблиц (кредиты Limey для исходного кода):
all <-data.frame()
for (i in 1:nrow(URL_file)) {
skip_to_next <- FALSE
tryCatch({
# Read the text files from the web
fileContents <- readr::read_file(URL_file$link[i])
# Extract the tables. The regex isn't quite right, as it includes the starting <TABLE>
# and ending </TABLE> tags, but more complicated regexes failed.
tables <- stringr::str_extract_all(
fileContents,
stringr::regex(
"(?s)<TABLE>(.*?)</TABLE>",
multiline = TRUE,
dotall = TRUE
)
)
# Function to process a single tibble
toTibble <- function(y) {
lines <- str_split_fixed(y, "\n", n = Inf)
colStarts <- c()
colEnds <- c()
# Scroll through to final table header
for (i in 1:(length(lines) - 1)) {
# Final line is '</TABLE>' because of initial regex
# Could probably to this with regexes, but my head is hurting
if (any(!is.na(stringr::str_locate(lines[i], "<\\w>")))) {
# Define column widths based on locations of type markers. THIS IS AN ASSUMPTION
colStarts <-
stringr::str_locate_all(lines[i], "<\\w>")[[1]][, "start"]
for (i in 1:(length(colStarts) - 1))
colEnds[i] <- colStarts[i + 1] - 1
colEnds[length(colStarts)] <- stringr::str_length(lines[i])
lines <- lines[(i + 1):(length(lines) - 1)]
data <- dplyr::bind_rows(lapply(
lines,
# For each data line
function(line)
tibble::enframe(# Split in to columns and convert to a tibble of name/value pairs
stringr::str_trim(
stringr::str_sub(line,
colStarts,
colEnds)
)) %>% # Convert from name/value pairs to columns
tidyr::pivot_wider(
values_from = "value",
names_from = "name",
names_prefix = "Column"
)
))
# Finished
return(data)
}
}
}
alldata <- bind_rows(lapply(tables[[1]], function(t)
toTibble(t)))
if (nrow(alldata) > 0) {
alldata$ID <- URL_file$ID[i]
}
#alldata$ID <- URL_file$ID[i]
all <- bind_rows(all, alldata)
print(i) #print every 10th value to monitor progress of the loop
}, error = function(e) {
skip_to_next <<- TRUE
})
if (skip_to_next) {
next
}
}
Примеры
Это пример входных таблиц (одна строка строки из каждого из вышеуказанных URL-адресов) - и это также идеальная структура
+-----------+-------------------------+----------------+-----------+--------------+-----------------+--------+----------+-----------------------+-------------+---------+--------+-------+
| (ID) | NAME OF ISSUER | TITLE OF CLASS | CUSIP | VALUE(x1000) | SHRS OR PRN AMT | SH/PRN | PUT/CALL | INVESTMENT DISCRETION | OTHER MNGRS | SOLE | SHARED | NONE |
+-----------+-------------------------+----------------+-----------+--------------+-----------------+--------+----------+-----------------------+-------------+---------+--------+-------+
| (1000097) | ABERCROMBIE & FITCH | CL A | 002896207 | 4,797 | 100,000 | SHS | | Shared-Defined | 1/2/3 | 100,000 | | |
| (1001085) | AMERICAN TOWER CORP NEW | COM | 03027X100 | 96566 | 1249724 | SH | | Defined | 1 | 1170124 | 0 | 79600 |
+-----------+-------------------------+----------------+-----------+--------------+-----------------+--------+----------+-----------------------+-------------+---------+--------+-------+
Текущий формат данных - это файл csv, разделенный запятыми:
ABERCROMBIE & FITCH,CL A,002896207,4,797,100,000,SHS,,Shared-Defined,1/2/3,100,000,,,1000097,NA,NA,NA,
AMERICAN TOWER CORP NEW,COM,03027X100,96566,1249724,SH,,Defined,1,1170124,0,,1001085,NA,NA,NA
Одна из основных проблем заключается в том, что вывод представляет собой файл, разделенный запятыми, и некоторые числа также разделены тысячами через ",". Дополнительный "," делает строки неравной длины.
Мысли и подходы
Я нашел несколько потенциальных подходов к этой проблеме:
Есть ли способ структурировать данные для желаемого результата? Или мне нужно извлекать таблицы другим способом? если да, как мне изменить приведенный выше код, чтобы он лучше соответствовал моим целям?