RODBC:积极转换字符和数字 (with/without as.is)
RODBC: chars and numerics converted aggressively (with/without as.is)
与 相关,我发现从 SQL 服务器 (2014) 提取数据时存在不一致的行为。
library(RODBC)
sqlQuery(.conn, "CREATE TABLE r2test ( [mychar] [NVARCHAR](16), [mynum] [FLOAT])")
# character(0)
sqlQuery(.conn, "INSERT INTO r2test (mychar,mynum) VALUES ('1',3.141593),('2',6.283185)")
character(0)
str(sqlQuery(.conn, "SELECT * FROM r2test", stringsAsFactors = FALSE))
# 'data.frame': 2 obs. of 2 variables:
# $ mychar: int 1 2
# $ mynum : num 3.14 6.28
在该示例中,我们看到了不良行为:mychar
的字符在内部被转换为整数。根据前面提到的 SO 答案,as.is
选项可以解决这个问题,但不幸的是,它也会将十进制表示的浮点数强制转换为字符串:
str(sqlQuery(.conn, "SELECT * FROM r2test", stringsAsFactors = FALSE, as.is = TRUE))
# 'data.frame': 2 obs. of 2 variables:
# $ mychar: chr "1" "2"
# $ mynum : chr "3.1415929999999999" "6.2831849999999996"
如果 mychar
中至少有一个实际上不是可整型的,那么一切都很好:
sqlQuery(.conn, "INSERT INTO r2test (mychar,mynum) VALUES ('a',9.424778)")
# character(0)
str(sqlQuery(.conn, "SELECT * FROM r2test", stringsAsFactors = FALSE))
# 'data.frame': 3 obs. of 2 variables:
# $ mychar: chr "1" "2" "a"
# $ mynum : num 3.14 6.28 9.42
不幸的是,数据模型不支持任意添加一些东西来鼓励这种行为(或者我只是没有想到一个足够好的方法来做到这一点)。数据模型使得 mychar
的值包括 01
和 1
,它们在字符方面是不同的。我发现的唯一解决方法是使用 as.is = TRUE
,这将需要我 as.numeric
所有相关的列,这是既乏味又(理论上)不必要的工作。
由于文档建议需要设置 DBMSencoding
,我检查了当前编码(在 的帮助下):
sqlQuery(.conn, "SELECT SERVERPROPERTY('Collation')")
# 1 SQL_Latin1_General_CP1_CI_AS
我已经尝试使用(为了好玩):DBMSencoding="latin1"
、DBMSencoding="UTF-8"
,并且明确地使用了默认的 DBMSencoding=""
,但行为没有任何变化。
如何鼓励不过度强制数据类型的行为?
目前在 ubuntu.
上使用 R-3.2.5 和 RODBC-1.3.13
如果我没理解错的话,我想这就是你要找的,
str(sqlQuery(
.conn,
"SELECT * FROM r2test",
stringsAsFactors = FALSE,
as.is = c(TRUE, FALSE)
))
#'data.frame': 2 obs. of 2 variables:
# $ mychar: chr "1" "2"
# $ mynum : num 3.14 6.28
其中 as.is
指定为逻辑向量(长度必须与结果集中的列数相同)。公平地说,这并不是很清楚。 sqlQuery
的手册页只是让您参考 read.table
中的 as.is
参数,其中指出:
Note that as.is is specified per column (not per variable) and so
includes the column of row names (if any) and any columns to be
skipped.
这种方法的缺点是您需要提前知道哪些列要转换,哪些不需要。我个人不明白 为什么 默认行为不只是将 SQL 字符类型映射到 R 字符类型,SQL 数字类型映射到 R 数字类型,等等,但也许在后端有一个很好的理由。自动将 '1'
、'2'
、... 转换为整数对我来说 而不是 似乎很像 "feature"。
与
library(RODBC)
sqlQuery(.conn, "CREATE TABLE r2test ( [mychar] [NVARCHAR](16), [mynum] [FLOAT])")
# character(0)
sqlQuery(.conn, "INSERT INTO r2test (mychar,mynum) VALUES ('1',3.141593),('2',6.283185)")
character(0)
str(sqlQuery(.conn, "SELECT * FROM r2test", stringsAsFactors = FALSE))
# 'data.frame': 2 obs. of 2 variables:
# $ mychar: int 1 2
# $ mynum : num 3.14 6.28
在该示例中,我们看到了不良行为:mychar
的字符在内部被转换为整数。根据前面提到的 SO 答案,as.is
选项可以解决这个问题,但不幸的是,它也会将十进制表示的浮点数强制转换为字符串:
str(sqlQuery(.conn, "SELECT * FROM r2test", stringsAsFactors = FALSE, as.is = TRUE))
# 'data.frame': 2 obs. of 2 variables:
# $ mychar: chr "1" "2"
# $ mynum : chr "3.1415929999999999" "6.2831849999999996"
如果 mychar
中至少有一个实际上不是可整型的,那么一切都很好:
sqlQuery(.conn, "INSERT INTO r2test (mychar,mynum) VALUES ('a',9.424778)")
# character(0)
str(sqlQuery(.conn, "SELECT * FROM r2test", stringsAsFactors = FALSE))
# 'data.frame': 3 obs. of 2 variables:
# $ mychar: chr "1" "2" "a"
# $ mynum : num 3.14 6.28 9.42
不幸的是,数据模型不支持任意添加一些东西来鼓励这种行为(或者我只是没有想到一个足够好的方法来做到这一点)。数据模型使得 mychar
的值包括 01
和 1
,它们在字符方面是不同的。我发现的唯一解决方法是使用 as.is = TRUE
,这将需要我 as.numeric
所有相关的列,这是既乏味又(理论上)不必要的工作。
由于文档建议需要设置 DBMSencoding
,我检查了当前编码(在 的帮助下):
sqlQuery(.conn, "SELECT SERVERPROPERTY('Collation')")
# 1 SQL_Latin1_General_CP1_CI_AS
我已经尝试使用(为了好玩):DBMSencoding="latin1"
、DBMSencoding="UTF-8"
,并且明确地使用了默认的 DBMSencoding=""
,但行为没有任何变化。
如何鼓励不过度强制数据类型的行为?
目前在 ubuntu.
上使用 R-3.2.5 和 RODBC-1.3.13如果我没理解错的话,我想这就是你要找的,
str(sqlQuery(
.conn,
"SELECT * FROM r2test",
stringsAsFactors = FALSE,
as.is = c(TRUE, FALSE)
))
#'data.frame': 2 obs. of 2 variables:
# $ mychar: chr "1" "2"
# $ mynum : num 3.14 6.28
其中 as.is
指定为逻辑向量(长度必须与结果集中的列数相同)。公平地说,这并不是很清楚。 sqlQuery
的手册页只是让您参考 read.table
中的 as.is
参数,其中指出:
Note that as.is is specified per column (not per variable) and so includes the column of row names (if any) and any columns to be skipped.
这种方法的缺点是您需要提前知道哪些列要转换,哪些不需要。我个人不明白 为什么 默认行为不只是将 SQL 字符类型映射到 R 字符类型,SQL 数字类型映射到 R 数字类型,等等,但也许在后端有一个很好的理由。自动将 '1'
、'2'
、... 转换为整数对我来说 而不是 似乎很像 "feature"。