Переменная вызова R внутри sqldf

Мне нужно выполнить цикл по операторам sqldf, и для этого мне нужно вызвать переменную цикла внутри кода sqldf:

Моя таблица "данные" может быть:

data <- read.table(text ="
    loaddate DaysRange DaysRangeNext
1 2014-03-16        30            30
2 2014-03-16         0             0
3 2014-03-16         0             0
4 2014-03-16        60            NA
5 2014-04-16        30            30
6 2014-04-16         0            30
"
,header = TRUE)

затем я форматирую loaddate как дату:

data$loaddate<-as.Date(as.character(data$loaddate), format='%Y-%m-%d')

Скажем, у меня есть вектор "loaddates":

loaddates<- unique(sort(data$loaddate))

И мне нужно запустить следующий код для каждой loaddate:

for (i in loaddates) {

sqldf("
SELECT D.LoadDate,D.DaysRange, D.DaysRangeNext, 
COUNT(*) AS clientes
FROM data AS D
WHERE D.loaddate = i
GROUP BY D.LoadDate,D.DaysRange, D.DaysRangeNext
ORDER BY D.DaysRange, D.DaysRangeNext
")        }

Но я получаю следующую ошибку:

Ошибка в sqliteSendQuery (con, statement, bind.data): ошибка в заявлении: нет такого столбца: i

Есть ли способ сохранить значение переменной и использовать его внутри цикла?

Спасибо.

ВЕРСИЯ:

Я пытался:

sqldf(
strwrap(sprintf("
SELECT D.LoadDate,D.DaysRange, D.DaysRangeNext, 
COUNT(*) AS clientes 
FROM data AS D
WHERE D.LoadDate = '%s'
GROUP BY D.LoadDate,D.DaysRange, D.DaysRangeNext
ORDER BY D.DaysRange, D.DaysRangeNext
",i),simplify=TRUE,width=1000000))

Но я получил:

> [1] loaddate      DaysRange     DaysRangeNext clientes      <0 rows>
> (or 0-length row.names)

person GabyLP    schedule 13.01.2015    source источник


Ответы (4)


Переменная i не будет заменена в запросе как есть. Вам нужно sprintf, чтобы присвоить ему значение. (Я также не знаю, нужно ли вам учитывать разрывные линии, но на всякий случай я привожу их ниже. Возможно, вам не нужен sqldf; в этом случае просто удалите strwrap).

#let's assume loaddates is the following:
loaddates <- 'something'

Один из способов получить запрос по своему усмотрению, то есть без разрывных строк и с i, принимающим нужные вам значения loaddates:

strwrap(sprintf("
                SELECT D.LoadDate,D.DaysRange, D.DaysRangeNext, 
                COUNT(*) AS clientes
                FROM deuda AS D
                WHERE D.loaddate = '%s'
                GROUP BY D.LoadDate,D.DaysRange, D.DaysRangeNext
                ORDER BY D.DaysRange, D.DaysRangeNext
                ",i),simplify=TRUE,width=1000000)

который выведет:

[1] "SELECT D.LoadDate,D.DaysRange, D.DaysRangeNext, COUNT(*) AS clientes FROM deuda AS D WHERE D.CodEmp = 'TGG' and D.loaddate = something GROUP BY D.LoadDate,D.DaysRange, D.DaysRangeNext ORDER BY D.DaysRange, D.DaysRangeNext"

Это то, что вам нужно в одной строке без разрывов или с неназначенной переменной i.

В вашем цикле должно быть:

for (i in loaddates) {

strwrap(sprintf("
                SELECT D.LoadDate,D.DaysRange, D.DaysRangeNext, 
                COUNT(*) AS clientes
                FROM deuda AS D
                WHERE D.loaddate = '%s'
                GROUP BY D.LoadDate,D.DaysRange, D.DaysRangeNext
                ORDER BY D.DaysRange, D.DaysRangeNext
                ",i),simplify=TRUE,width=1000000)

}

С вашим набором данных:

library(sqldf)
data <- read.table(text ="
    loaddate DaysRange DaysRangeNext
1 2014-03-16        30            30
2 2014-03-16         0             0
3 2014-03-16         0             0
4 2014-03-16        60            NA
5 2014-04-16        30            30
6 2014-04-16         0            30
"
                   ,header = TRUE,stringsAsFactors=F)

loaddates<- unique(sort(data$loaddate))

for (i in loaddates) {

  print(sqldf(
  strwrap(sprintf("
                SELECT D.LoadDate,D.DaysRange, D.DaysRangeNext, 
                COUNT(*) AS clientes
                FROM data AS D
                WHERE D.loaddate = '%s'
                GROUP BY D.LoadDate,D.DaysRange, D.DaysRangeNext
                ORDER BY D.DaysRange, D.DaysRangeNext
                ",i),simplify=TRUE,width=1000000) ))
}

Выход:

    loaddate DaysRange DaysRangeNext clientes
1 2014-03-16         0             0        2
2 2014-03-16        30            30        1
3 2014-03-16        60            NA        1
    loaddate DaysRange DaysRangeNext clientes
1 2014-04-16         0            30        1
2 2014-04-16        30            30        1
person LyzandeR    schedule 13.01.2015
comment
Требовались кавычки около %s. Попробуй это сейчас. Я его обновил. - person LyzandeR; 13.01.2015
comment
тот же результат с кавычками - person GabyLP; 13.01.2015
comment
но мои работы я только что запустил! скопируйте мой пример и проверьте. Вам нужно print там, чтобы увидеть это. Вы также не добавили столбец в свой набор данных CodEmp - person LyzandeR; 13.01.2015
comment
btw loaddate столбец в данных имеет тип character, как я его использую. Ваш Date типаж? - person LyzandeR; 13.01.2015
comment
Проблема была в печати. Спасибо. - person GabyLP; 13.01.2015
comment
:) Рад, что помог (хотя мне потребовалось несколько попыток) !! - person LyzandeR; 13.01.2015
comment
Я думаю, проблема в том, что дата должна быть представлена ​​в виде строки. Если вы сохраните его как дату, код не будет работать (или вы должны отформатировать дату в sprintf) - person Barranka; 13.01.2015
comment
@Barranka Спасибо за комментарий. Кажется, работает так, как вы предлагаете. - person LyzandeR; 13.01.2015

Вы можете заставить это работать, определив свой оператор SQL в цикле, но вне вызова функции.

for (i in loaddates) {

statement = paste( " SELECT D.LoadDate,D.DaysRange, D.DaysRangeNext,
              COUNT(*) AS clientes
              FROM data AS D
              WHERE D.loaddate = ", i,
"GROUP BY D.LoadDate,D.DaysRange, D.DaysRangeNext
ORDER BY D.DaysRange, D.DaysRangeNext " )

sqldf(statement)
}
person Nilesh    schedule 14.01.2015

Сначала создайте новый фрейм данных. Тогда присоединяйтесь к нему:

num_Pcode <- as.numeric("3550")
df_Pcode_0 <- as.data.frame(num_Pcode)
df_Pcode_0
...

возвращает num_Pcode.

person maRRRRk    schedule 23.04.2018

fn$sqldf позволяет использовать $ в операторе sql для интерполяции переменных R. См. Пример 5 на домашней странице sqldf github и внизу страницы справки ?fn множество других примеров. Мы могли бы уменьшить setNames(loaddates, loaddates) до loaddates, если нам не нужны имена на выходе.

Map(function(i)
  fn$sqldf("
    SELECT D.LoadDate,D.DaysRange, D.DaysRangeNext, 
    COUNT(*) AS clientes
    FROM data AS D
    WHERE D.loaddate = $i
    GROUP BY D.LoadDate,D.DaysRange, D.DaysRangeNext
    ORDER BY D.DaysRange, D.DaysRangeNext
  "), setNames(loaddates, loaddates))

давая:

$`2014-03-16`
    loaddate DaysRange DaysRangeNext clientes
1 2014-03-16         0             0        2
2 2014-03-16        30            30        1
3 2014-03-16        60            NA        1

$`2014-04-16`
    loaddate DaysRange DaysRangeNext clientes
1 2014-04-16         0            30        1
2 2014-04-16        30            30        1
person G. Grothendieck    schedule 24.04.2018