rio和haven从SPSS导入时,随机将日期列中的NA解释为1582-10-14

to94eoyn  于 2023-03-20  发布在  其他
关注(0)|答案(1)|浏览(135)

我正在从SPSS导入数据(sav文件)。在这个数据集中有几个日期列,其中几个包含有缺失值的单元格。所有日期列都作为日期变量导入到R中,到目前为止一切顺利。来自SPSS的所有日期条目都正确导入到R中,到目前为止仍然一切顺利。然而,SPSS中的一些缺失值在导入到R时被解释为1582-10-14。我知道这是公历的开始,所以我想也许SPSS中的一些单元格是0而不是NA,但当检查所说的单元格时,它们实际上是空的,并且看起来与在R中被正确导入为NA的其它空单元完全相同。
我很抱歉我想不出一个可复制的例子,我不能把我的SPSS文件在这里,完整性的原因。
我试过用rio(import_list)和haven(read_sav)导入,同样的单元格用两种方法都解释为1582-10-14,可能不是随机的,SPSS文件中有一些隐藏的数据在SPSS界面看不到?
知道为什么我会得到这个错误吗?会不会是一个bug?不过我的经验是很少有。还有人经历过这种情况吗?
一个可能的修正方法是删除R中的所有1582-10-14条目,但我想知道它发生的原因。如果从SPSS导入的数据不正确怎么办?
编辑:This post已经被建议作为一个解决方案,但它不是。这篇文章涉及R从SPSS导入日期作为绝对数字从1582-10-14和如何将这些值转换为实际日期,如果我理解正确。这篇文章涉及R错误地解释了一些缺失的值的SPSS日期列为1582-10-14。
这是一个SPSS中的数据截图,以及导入到R后的数据截图。

Link to SPSS dataset

datetest <- structure(list(datevariable = structure(c(NA, 18394, 
 NA, 17914, -141428, -141428, NA, -141428, NA, NA, NA, 
 -141428, NA, NA, -141428, -141428, NA, NA, NA, NA, NA, 
 NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 17765, NA, NA, 
 NA, NA, NA, NA, NA, -141428, NA, NA, NA, NA, NA, NA, NA,
 19278, NA, NA, NA, NA, NA, NA, NA, 19121, NA, NA, NA, 
 NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
 NA, NA, NA, NA), label = "datevariable", class = "Date", format.spss = "SDATE10")),
     class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -77L))

如您所见,行号2和4被正确导入。行5、6、8、12、15...的缺失值被导入为1582-10-14。

tjvv9vkg

tjvv9vkg1#

我有一个不完整的,可能不满意的答案。
我下载了您的文件并运行了以下代码:

library(foreign)
library(rio)
x1 <- read.spss("spss_test.sav")
x2 <- rio::import("spss_test.sav")
x3 <- haven::read_spss("spss_test.sav")

实际上,rio只是haven或(或者,如果需要)foreign包,因此x2是冗余的......我使用下面定义的print_hex()函数检查了结果,并在Emacs中以“hexl模式”查看文件(我想你可以在网上找到其他的十六进制编辑器等等)比较foreign::read.spss()haven::read_spss()的优点是read.spss实际上做了 * 更少 * 的数据处理(产生奇怪的长数字,然后可以转换成日期),这使得它更容易看到发生了什么。
查看结果,比较x1[[i]](数值)的前几个元素;print_hex(x1[[i]])(底层十六进制表示);和x3[[i]](日期值),我们得到

  • 要素1和3:不适用,7 ff 000000007 a2,不适用
  • 要素2:13808620800、4209 b876 a8000000,2020年5月12日
  • 元件4:13767148800,4209 a4 b 028000000,2019年1月18日
  • 元素5:0、0、1582年10月14日

因此,一些缺失值被SPSS编码为零,一些被编码为NA值,这是肯定的,不幸的是,为什么缺失值被不同地编码,对我来说是一个谜。
我试着查看原始的十六进制代码转储,但是很痛苦,而且没有多大帮助。在下面第2行的末尾,您可以看到对应于编码为00 0000 a876 b809 42的元素2的十六进制值,它是 * 向后反转顺序 *,即从最后一对开始(42)并从右向左读取每一对(09,b8,76...)。元素4的值似乎就在它后面(第2行结束,第3行开始)。这是我迷失的地方,因为我不知道在文件编码中正在做什么样的压缩/其他魔术...

01           0000 5554 462d 38e7 0300 0000 0000 00ff  ..UTF-8.........
02 000001f0: fdff fd64 64ff 6400 0000 a876 b809 4200  ...dd.d....v..B.
03 00000200: 0000 28b0 a409 42ff ffff 64ff ff64 64ff  ..(...B...d..dd.
04 00000210: ffff ffff ffff ffff ffff ffff ffff fd00  ................
05 00000220: 0000 ac8c 9e09 42ff ffff ffff ffff 64ff  ......B.......d.

Double precision (64-bit) representation of numeric value in R (sign, exponent, significand)开始:

Rcpp::cppFunction('void print_hex(double x) {
    uint64_t y;
    static_assert(sizeof x == sizeof y, "Size does not match!");
    std::memcpy(&y, &x, sizeof y);
    Rcpp::Rcout << std::hex << y << std::endl;
}', plugins = "cpp11", includes = "#include <cstdint>")

相关问题