Update app.R
Browse files
app.R
CHANGED
|
@@ -188,6 +188,166 @@ download_private_parquet <- function(repo_id, filename) {
|
|
| 188 |
}
|
| 189 |
}
|
| 190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
MLB25 <- download_private_parquet("TimStats/StatcastDataAll", "MLB25.parquet")
|
| 192 |
MLB25$level <- "MLB"
|
| 193 |
AAA25 <- download_private_parquet("TimStats/StatcastDataAll", "AAA25.parquet")
|
|
|
|
| 188 |
}
|
| 189 |
}
|
| 190 |
|
| 191 |
+
download_private_parquet <- function(repo_id, filename) {
|
| 192 |
+
library(httr)
|
| 193 |
+
|
| 194 |
+
# Main URL for direct file download
|
| 195 |
+
url <- paste0("https://huggingface.co/datasets/", repo_id, "/resolve/main/", filename)
|
| 196 |
+
|
| 197 |
+
# Download with retry for reliability
|
| 198 |
+
temp_file <- tempfile(fileext = paste0(".", tools::file_ext(filename)))
|
| 199 |
+
|
| 200 |
+
cat("Downloading from URL:", url, "\n")
|
| 201 |
+
|
| 202 |
+
response <- RETRY(
|
| 203 |
+
"GET",
|
| 204 |
+
url,
|
| 205 |
+
add_headers(Authorization = paste("Bearer", Sys.getenv("GETCSV"))),
|
| 206 |
+
write_disk(temp_file, overwrite = TRUE),
|
| 207 |
+
times = 3
|
| 208 |
+
)
|
| 209 |
+
|
| 210 |
+
if (status_code(response) == 200) {
|
| 211 |
+
# Check file size
|
| 212 |
+
file_info <- file.info(temp_file)
|
| 213 |
+
cat("File downloaded, size:", file_info$size, "bytes\n")
|
| 214 |
+
|
| 215 |
+
if (file_info$size == 0) {
|
| 216 |
+
file.remove(temp_file)
|
| 217 |
+
stop("Downloaded file is empty")
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
# Check if this is an LFS pointer (small text file)
|
| 221 |
+
if (file_info$size < 1000) {
|
| 222 |
+
tryCatch({
|
| 223 |
+
content_text <- readLines(temp_file, n = 1, warn = FALSE)
|
| 224 |
+
|
| 225 |
+
if (grepl("^version https://git-lfs.github.com/spec/", content_text)) {
|
| 226 |
+
# It's an LFS pointer - read all lines
|
| 227 |
+
all_lines <- readLines(temp_file, warn = FALSE)
|
| 228 |
+
|
| 229 |
+
# Extract oid
|
| 230 |
+
oid_line <- grep("oid sha256:", all_lines, value = TRUE)
|
| 231 |
+
oid <- gsub("oid sha256:", "", oid_line)
|
| 232 |
+
oid <- trimws(oid)
|
| 233 |
+
|
| 234 |
+
# Try the Hugging Face LFS URL format
|
| 235 |
+
lfs_url <- paste0("https://huggingface.co/datasets/", repo_id, "/resolve/main/", filename, "?download=true")
|
| 236 |
+
|
| 237 |
+
cat("Detected LFS pointer. Downloading from:", lfs_url, "\n")
|
| 238 |
+
|
| 239 |
+
# Download actual content
|
| 240 |
+
lfs_response <- RETRY(
|
| 241 |
+
"GET",
|
| 242 |
+
lfs_url,
|
| 243 |
+
add_headers(Authorization = paste("Bearer", Sys.getenv("GETCSV"))),
|
| 244 |
+
write_disk(temp_file, overwrite = TRUE),
|
| 245 |
+
times = 3
|
| 246 |
+
)
|
| 247 |
+
|
| 248 |
+
if (status_code(lfs_response) != 200) {
|
| 249 |
+
file.remove(temp_file)
|
| 250 |
+
stop(paste("Failed to download LFS content. Status code:", status_code(lfs_response)))
|
| 251 |
+
}
|
| 252 |
+
|
| 253 |
+
file_info <- file.info(temp_file)
|
| 254 |
+
cat("LFS file downloaded, size:", file_info$size, "bytes\n")
|
| 255 |
+
}
|
| 256 |
+
}, error = function(e) {
|
| 257 |
+
cat("Not an LFS pointer or error reading it:", e$message, "\n")
|
| 258 |
+
})
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
# Try to detect file type by reading first few bytes
|
| 262 |
+
con <- file(temp_file, "rb")
|
| 263 |
+
header <- readBin(con, "raw", n = 8)
|
| 264 |
+
close(con)
|
| 265 |
+
|
| 266 |
+
# Convert to character for inspection
|
| 267 |
+
header_str <- rawToChar(header)
|
| 268 |
+
|
| 269 |
+
# Create a download path in the working directory for reference
|
| 270 |
+
download_path <- file.path(getwd(), basename(filename))
|
| 271 |
+
file.copy(temp_file, download_path, overwrite = TRUE)
|
| 272 |
+
cat("File copied to:", download_path, "\n")
|
| 273 |
+
|
| 274 |
+
# Try different file formats based on header or extension
|
| 275 |
+
if (grepl("PAR1", header_str)) {
|
| 276 |
+
# It's a parquet file
|
| 277 |
+
cat("Detected parquet format\n")
|
| 278 |
+
library(arrow)
|
| 279 |
+
tryCatch({
|
| 280 |
+
data <- read_parquet(temp_file)
|
| 281 |
+
file.remove(temp_file)
|
| 282 |
+
return(data)
|
| 283 |
+
}, error = function(e) {
|
| 284 |
+
cat("Error reading as parquet:", e$message, "\n")
|
| 285 |
+
cat("Try reading manually with arrow::read_parquet('", download_path, "')\n", sep = "")
|
| 286 |
+
stop(paste("Error reading parquet file:", e$message))
|
| 287 |
+
})
|
| 288 |
+
} else if (grepl("^PK", header_str)) {
|
| 289 |
+
# It's a zip/xlsx file
|
| 290 |
+
cat("Detected zip/xlsx format\n")
|
| 291 |
+
if (grepl("\\.xlsx$", filename, ignore.case = TRUE)) {
|
| 292 |
+
library(readxl)
|
| 293 |
+
tryCatch({
|
| 294 |
+
data <- read_excel(temp_file)
|
| 295 |
+
file.remove(temp_file)
|
| 296 |
+
return(data)
|
| 297 |
+
}, error = function(e) {
|
| 298 |
+
cat("Error reading as Excel:", e$message, "\n")
|
| 299 |
+
cat("Try reading manually with readxl::read_excel('", download_path, "')\n", sep = "")
|
| 300 |
+
stop(paste("Error reading Excel file:", e$message))
|
| 301 |
+
})
|
| 302 |
+
} else {
|
| 303 |
+
cat("Zip file detected. Cannot automatically process.\n")
|
| 304 |
+
cat("File is available at:", download_path, "\n")
|
| 305 |
+
stop("Downloaded file appears to be a zip file. Please process manually.")
|
| 306 |
+
}
|
| 307 |
+
} else {
|
| 308 |
+
# Try as CSV
|
| 309 |
+
cat("Trying as CSV/text format\n")
|
| 310 |
+
|
| 311 |
+
# Check if it looks like text
|
| 312 |
+
can_be_text <- tryCatch({
|
| 313 |
+
readLines(temp_file, n = 1, warn = FALSE)
|
| 314 |
+
TRUE
|
| 315 |
+
}, error = function(e) {
|
| 316 |
+
FALSE
|
| 317 |
+
})
|
| 318 |
+
|
| 319 |
+
if (can_be_text) {
|
| 320 |
+
tryCatch({
|
| 321 |
+
data <- read.csv(temp_file, header = TRUE, stringsAsFactors = FALSE, fileEncoding = "UTF-8")
|
| 322 |
+
file.remove(temp_file)
|
| 323 |
+
return(data)
|
| 324 |
+
}, error = function(e) {
|
| 325 |
+
cat("Error reading as CSV:", e$message, "\n")
|
| 326 |
+
|
| 327 |
+
# Try reading as TSV
|
| 328 |
+
tryCatch({
|
| 329 |
+
data <- read.delim(temp_file, header = TRUE, stringsAsFactors = FALSE, fileEncoding = "UTF-8")
|
| 330 |
+
file.remove(temp_file)
|
| 331 |
+
return(data)
|
| 332 |
+
}, error = function(e2) {
|
| 333 |
+
cat("Error reading as TSV:", e2$message, "\n")
|
| 334 |
+
cat("File is available at:", download_path, "\n")
|
| 335 |
+
cat("Try examining the file manually to determine format\n")
|
| 336 |
+
stop("Could not automatically determine file format")
|
| 337 |
+
})
|
| 338 |
+
})
|
| 339 |
+
} else {
|
| 340 |
+
cat("File does not appear to be text-based\n")
|
| 341 |
+
cat("File is available at:", download_path, "\n")
|
| 342 |
+
stop("Could not automatically determine file format. Please check the downloaded file.")
|
| 343 |
+
}
|
| 344 |
+
}
|
| 345 |
+
} else {
|
| 346 |
+
file.remove(temp_file)
|
| 347 |
+
stop(paste("Failed to download dataset. Status code:", status_code(response)))
|
| 348 |
+
}
|
| 349 |
+
}
|
| 350 |
+
|
| 351 |
MLB25 <- download_private_parquet("TimStats/StatcastDataAll", "MLB25.parquet")
|
| 352 |
MLB25$level <- "MLB"
|
| 353 |
AAA25 <- download_private_parquet("TimStats/StatcastDataAll", "AAA25.parquet")
|