我正在使用 R,其中我有一個變數'2 month 3 day 6 hour 70 minute'作為字串。變數隨時間變化,因此不具有相同的長度/結構。我需要這個變數通過將其轉換為間隔來對 PostgreSQL 資料庫進行查詢。這作業得很好。
現在我需要這個間隔/字串變數在幾分鐘內作為整數來做一些數學計算。
我想到了使用sqldf如下:
library(sqldf)
my_interval = '2 month 3 day 6 hour 70 minute'
interval_minutes <- sqldf(paste("SELECT EXTRACT(EPOCH FROM '",my_interval,"'::INTERVAL)/60"))
interval_minutes_novar <- sqldf("SELECT EXTRACT(EPOCH FROM '2 month 3 day 6 hour 70 minute'::INTERVAL)/60")
但我得到了Error: near "FROM": syntax error。根據我的研究,我知道sqldf使用 SQLite,它不支持EXTRACT().
如何使用 R 將 SQL 間隔轉換為分鐘?
uj5u.com熱心網友回復:
1) sqldf/gsubfn使用 gsubfn 將 my_interval 中的每個單詞替換為 *、適當的分鐘數和 。洗掉任何尾隨 和空格,然后決議和評估 mins 或將 mins 替換為 sql 陳述句。4 個日歷年的平均每月有 365.25 / 12 天,有一個閏年,但如果您想獲得與 PostgreSQL 相同的答案,請將 365.25 / 12 替換為 30,如評論中所述。
library(sqldf) # this also pulls in gsubfn
# input
my_interval = '2 month 3 day 6 hour 70 minute'
L <- list(minute = " ", hour = "*60 ", day = "*60*24 ",
month = "*365.25 * 60 * 24 /12 ")
mins <- my_interval |>
gsubfn(pattern = "\\w ", replacement = L) |>
trimws(whitespace = "[ ]")
eval(parse(text = mins))
## [1] 92410
fn$sqldf("select $mins mins")
## mins
## 1 92410
2) 基礎 R這是基礎 R 解決方案。將數字和單詞提取到單獨的向量中,將單詞轉換為適當的因子并取它們的內積。(1) 中關于每月 30 天的討論也適用于此。
v <- c(minute = 1, hour = 60, day = 60 * 24, month = 365.25 * 60 * 24 /12)
nums <- my_interval |>
gsub(pattern = "[a-z]", replacement = "") |>
textConnection() |>
scan(quiet = TRUE)
words <- my_interval |>
gsub(pattern = "\\d", replacement = "") |>
textConnection() |>
scan(what = "", quiet = TRUE)
sum(v[words] * nums)
## [1] 92410
3) lubridate 可以使用 lubridate 持續時間物件。
library(lubridate)
as.numeric(duration(my_interval), "minute")
## [1] 92410
雖然 lubridate 不能處理 30 天的月份(哈德利說沒有計劃),但我們可以預處理 my_interval 以獲得效果。
library(gsubfn)
library(lubridate)
my_interval |>
gsubfn(pattern = "(\\d ) month", replacement = ~paste(30*as.numeric(x),"day")) |>
duration() |>
as.numeric("minute")
## [1] 91150
uj5u.com熱心網友回復:
在這里調整我的答案,我將重申這個轉換的一個相當大的問題:將“月”轉換為“秒”不是恒定的,因為月份在 28-31 天之間變化。但是,如果我們為了爭論而假設 30,那么:
func <- function(x, ptn) {
out <- gsub(paste0(".*?\\b([0-9.] )\\s*", ptn, ".*"), "\\1", x, ignore.case = TRUE)
ifelse(out == x, NA, out)
}
res1 <- lapply(c(mon = "month", day = "day", hr = "hour", min = "minute"),
function(ptn) as.numeric(func(my_interval, ptn)))
res2 <- lapply(res1, function(z) ifelse(is.na(z), 0, z))
res2
# $mon
# [1] 2
# $day
# [1] 3
# $hr
# [1] 6
# $min
# [1] 70
86400 * (res2$mon*31 res2$day) 3600*res2$mon 60*res2$hr
# [1] 5623560
因為我在這里使用簡單的矢量化操作,所以如果有多個字串(格式相似)lapply,這也可以作業。my_interval它對缺失變數(假定0)是穩健的,并且可以包括“年”(盡管閏年不準確)和/或“秒”(如果需要)。
intervals <- c("2 month 3 day 6 hour 70 minute", "1 year", "1 hour 1 second")
res1 <- lapply(c(yr = "year", mon = "month", day = "day", hr = "hour", min = "minute", sec = "second"),
function(ptn) as.numeric(func(intervals, ptn)))
res2 <- lapply(res1, function(z) ifelse(is.na(z), 0, z))
str(res2)
# List of 6
# $ yr : num [1:3] 0 1 0
# $ mon: num [1:3] 2 0 0
# $ day: num [1:3] 3 0 0
# $ hr : num [1:3] 6 0 1
# $ min: num [1:3] 70 0 0
# $ sec: num [1:3] 0 0 1
86400 * (res2$yr*365 res2$mon*31 res2$day) 3600*res2$mon 60*res2$hr res2$sec
# [1] 5.6e 06 3.2e 07 6.1e 01
uj5u.com熱心網友回復:
我的解決方法是使用我的 PostgreSQL 連接來做到這一點:
library(sf)
library(RPostgres)
my_postgresql_connection <- dbConnect(Postgres(), dbname = "my_db", host = "my_host", port = 1234, user = "my_user", password = "my_password")
my_interval = '2 month 3 day 6 hour 70 minute'
my_dataframe <- st_read(my_postgresql_connection, query = paste("SELECT EXTRACT(EPOCH FROM '",my_interval,"'::INTERVAL)/60 as minutes"))
my_interval_in_minutes <- as.double(my_dataframe$minutes[1])
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/411061.html
標籤:
上一篇:如果值為空,則跳過插入查詢
