2017-12-21 17 views
1

以下のサンプルコードのように、sqldfを使用して日付範囲に基づいてデータフレームをフィルタリングしようとしています。私は以下の例のデータのようなデータを持っています。 sqldfによって返されるdatedfデータフレームにはレコードがありません。その日付範囲内のSHVデータフレームにレコードがあります。誰かが間違っていることを見ることができ、日付範囲でフィルタリングする方法をsqldfで教えてください。私のために日付は常に難しいです。データのこのサンプルで日付範囲(sqldf)のフィルタ

Code: 
datedf<-sqldf("select field1        
      ,fieldDate 
          from SHV 
          where fieldDate between '2004-01-01' and '2005-01-01' 
          ") 


Data: 

dput(SHV[1:50,c("field1","fieldDate")]) 
structure(list(field1 = c(1378L, 1653L, 1882L, 2400L, 
2305L, 2051L, 2051L, 2051L, 1796L, 2054L, 2568L, 1290L, 1804L, 
1804L, 3855L, 1297L, 2321L, 2321L, 2321L, 2071L, 2071L, 2074L, 
2588L, 1567L, 1317L, 1317L, 808L, 808L, 1321L, 2350L, 1586L, 
2613L, 1590L, 2614L, 2107L, 1340L, 1085L, 1085L, 2365L, 1344L, 
1601L, 1858L, 1603L, 1603L, 1860L, 2376L, 1355L, 1867L, 2382L, 
1872L), fieldDate = structure(c(12551, NA, NA, 14057, 15337, 
12919, 13336, 10325, 14984, 15643, 12864, 11242, 10749, 11207, 
10602, NA, 12646, 15649, NA, NA, NA, NA, NA, 17015, 13938, NA, 
16693, NA, NA, 12634, 12614, 10689, 12755, 10844, 11375, 4899, 
17298, 10905, 11450, NA, 10330, 15429, 12634, 10504, 12625, 11081, 
10939, NA, 12934, 11176), class = "Date")), .Names = c("field1", 
"fieldDate"), row.names = c(NA, 50L), class = "data.frame") 
+0

その日付範囲のレコードはありません。 – suchait

+0

SQLiteには日付または時刻データ型がないため、Dateクラスの変数をEpochからの日数であるR Date型の内部表現として送信します。デフォルトのRSQLiteバックエンドの代わりにRH2バックエンド(H2に日付型があります)を使用すると、SQL文はそのまま動作します。 'ライブラリ(sqldf);ライブラリ(RH2); sqldf(... your statement ...) ' –

答えて

0

あなたは、その日付の範囲内ではレコードがありません:this articleによると

SHV[SHV$fieldDate >= "2010-01-01" & SHV$fieldDate < "2011-01-01",] 
    field1 fieldDate 
NA  NA  <NA> 
NA.1  NA  <NA> 
NA.2  NA  <NA> 
NA.3  NA  <NA> 
NA.4  NA  <NA> 
NA.5  NA  <NA> 
NA.6  NA  <NA> 
NA.7  NA  <NA> 
NA.8  NA  <NA> 
NA.9  NA  <NA> 
NA.10  NA  <NA> 
NA.11  NA  <NA> 
NA.12  NA  <NA> 
+0

合意 - 2008-06-06と2011-01-01の間にギャップがあります。しかし構文には問題があります。 2000から2011までの範囲を拡張すると、ゼロ行が返されます。 – wibeasley

+0

@wibeasleyありがとうございます。はい、サンプルデータをチェックして、日付範囲にレコードがあることを確認しませんでした。元の投稿を更新して、サンプル日付の日付範囲のレコードが表示されるようにしました。私のコードで何が問題になっているのか見ていますか? – modLmakur

-1

を、日付フィールドはsqldfを実行する前に、文字に変換する必要があります。

日付をSQLdfに渡す前に、まず文字列に変換する必要があります。それ以外の場合、SQLdfはそれらを数値として扱うことになります。これは心苦しいものになります。

...

代わりに、我々は代わりに、日付の文字列にDateCreated列を変換する必要があります。 SQLは実際には文字列から日付に変換されます。

混乱していますか?私が私自身でこれを理解しようとしていた時、私が想像してみてください。

だからあなたのコードは次のようになります。

SHV$fieldDate <- as.character(SHV$fieldDate) 

datedf <- sqldf(" 
    SELECT 
    field1, 
    fieldDate 
    FROM SHV 
    WHERE fieldDate between '2004-01-01' and '2005-01-01' 
    --WHERE '2004-01-01' <= fieldDate --and fieldDate <= '2005-01-01' 
    ORDER BY fieldDate 
") 

# Both should equal 7. Verify that null rows are handled as desired. 
nrow(datedf) 
sum(as.Date('2004-01-01') <= SHV$fieldDate & SHV$fieldDate <= as.Date('2005-01-01'), na.rm=T) 

私はそれが実際の日付に日付を見据えた変数をキャストする場合についてもう少し説明があればいいのに。もっと見ると、@ g-grothendieckによるこのSO responseは、sqldfクエリー内のデータ型とは異なるアプローチをとります。

+0

数字の日付値を文字に変換することは、 '%d-%m-%Y'のようにすべての日付形式で正しく機能しないため、危険です。文字比較'12 -01-2004 '> '01 -02- 2004年2月1日が2004年1月12日を超えていても、2004年はTRUEを返します。 –

+0

as.character(SHV $ fieldDate)は、常に[ISO 8601](https:// xkcd。 com/1179 /)。このコードでは '%d-%m-%Y'のようなものは必要ありません。これは、Date型として開始されるためです。 – wibeasley

+0

この特定の例では、 '%d-%m-%Y'のようなものは必要ないということに同意します。これは、2つの日付間の文字比較が間違った答えを返す状況を説明するためのものです。私はコーダーがこのタイプの比較で複数のプログラミング言語で欠陥を生成するのを見てきました。 –

0

sqldf()documentationによれば、日付を数値として処理して日付として処理する必要があります。これは、SQLクエリを生成するときにsprintf()で実行できます。

SHV <- structure(list(field1 = c(1378L, 1653L, 1882L, 2400L, 
          2305L, 2051L, 2051L, 2051L, 1796L, 2054L, 2568L, 1290L, 1804L, 
          1804L, 3855L, 1297L, 2321L, 2321L, 2321L, 2071L, 2071L, 2074L, 
          2588L, 1567L, 1317L, 1317L, 808L, 808L, 1321L, 2350L, 1586L, 
          2613L, 1590L, 2614L, 2107L, 1340L, 1085L, 1085L, 2365L, 1344L, 
          1601L, 1858L, 1603L, 1603L, 1860L, 2376L, 1355L, 1867L, 2382L, 
          1872L), fieldDate = structure(c(12551, NA, NA, 14057, 15337, 
                   12919, 13336, 10325, 14984, 15643, 12864, 11242, 10749, 11207, 
                   10602, NA, 12646, 15649, NA, NA, NA, NA, NA, 17015, 13938, NA, 
                  16693, NA, NA, 12634, 12614, 10689, 12755, 10844, 11375, 4899, 
                  17298, 10905, 11450, NA, 10330, 15429, 12634, 10504, 12625, 11081, 
                  10939, NA, 12934, 11176), class = "Date")), .Names = c("field1", 
                               "fieldDate"), row.names = c(NA, 50L), class = "data.frame") 

library(sqldf) 
sqlStmt <- paste("select field1, fieldDate from SHV", 
       "where fieldDate between ", 
       sprintf("%d and %d",as.Date('2004-01-01','%Y-%m-%d'), 
        as.Date('2005-01-01','%Y-%m-%d'))) 
datedf<-sqldf(sqlStmt) 
datedf 

> datedf 
    field1 fieldDate 
1 1378 2004-05-13 
2 2321 2004-08-16 
3 2350 2004-08-04 
4 1586 2004-07-15 
5 1590 2004-12-03 
6 1603 2004-08-04 
7 1860 2004-07-26 
> 

sprintf()ステートメントは、SQLでbetweenオペレータが正常に動作することが保証された数値、日付を変換します。

> sqlStmt 
[1] "select field1, fieldDate from SHV where fieldDate between 12418 and 12784" 
> 
+1

これは次のように単純化できます: 'fromDate < - as.Date( '2004-01-01'); toDate < - as.Date( '2005-01-01');fn $ sqldf( "フィールド1を選択し、SHVからfieldDateを取得し、$ fromDateと$ toDateの間のfieldDate") ' –