将用 SPSS 编写的小型数据集转换为 CSV

Convert a small dataset written in SPSS to CSV

我有一个用 SPSS 语法编写的小数据集,它来自 Table 5.3 p. 189 of this book在页槽中键入 210 以查看 table).

我想知道是否有办法将此数据转换为 .csv 文件? (后面我想用R里面的数据)

# SPSS Code:

DATA LIST FREE/gpid anx socskls assert.
BEGIN DATA.
1 5 3 3     1 5 4 3     1 4 5 4     1 4 5 4
1 3 5 5     1 4 5 4     1 4 5 5     1 4 4 4
1 5 4 3     1 5 4 3     1 4 4 4
2 6 2 1     2 6 2 2     2 5 2 3     2 6 2 2
2 4 4 4     2 7 1 1     2 5 4 3     2 5 2 3
2 5 3 3     2 5 4 3     2 6 2 3
3 4 4 4     3 4 3 3     3 4 4 4     3 4 5 5
3 4 5 5     3 4 4 4     3 4 5 4     3 4 6 5
3 4 4 4     3 5 3 3     3 4 4 4
END DATA.

编辑 - 为了检查答案,我在此处添加数据在 SPSS 中读取后的实际方式:

gpid   anx  socskls   assert
1       5       3       3
1       5       4       3
1       4       5       4
1       4       5       4
1       3       5       5
1       4       5       4
1       4       5       5
1       4       4       4
1       5       4       3
1       5       4       3
1       4       4       4
2       6       2       1
2       6       2       2
2       5       2       3
2       6       2       2
2       4       4       4
2       7       1       1
2       5       4       3
2       5       2       3
2       5       3       3
2       5       4       3
2       6       2       3
3       4       4       4
3       4       3       3
3       4       4       4
3       4       5       5
3       4       5       5
3       4       4       4
3       4       5       4
3       4       6       5
3       4       4       4
3       5       3       3
3       4       4       4

这需要在记事本或类似工具中进行一些手动清理,以正确的格式放置数据。但本质上,这可以使用以下内容导入

df <- data.frame(
  gpid = c(1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,
                 2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3),
  anx = c(5,5,4,4,3,4,4,4,5,5,4,6,6,5,6,
                 4,7,5,5,5,5,6,4,4,4,4,4,4,4,4,4,5,4),
  socskls = c(3,4,5,5,5,5,5,4,4,4,4,2,2,2,2,
                 4,1,4,2,3,4,2,4,3,4,5,5,4,5,6,4,3,4),
  assert = c(3,3,4,4,5,4,5,4,3,3,4,1,2,3,2,
                 4,1,3,3,3,3,3,4,3,4,5,5,4,4,5,4,3,4)
)

write.csv(df, "df.csv", row.names = F)

请注意,前 4 个值(1、5、3、3)是第 1 行的 gpid、anx、socskls 和断言值。而值 1、5、4、3 似乎在SPSS 语法中粘贴数据的下一列(即从左到右阅读语法的下 4 个值)实际上是参与者 10 的值。

注意:我假设您没有安装 SPSS。如果你做了最简单的选择,那就是使用 SPSS 语法在 SPSS 中创建数据集,然后导出到 R。

使用readLines和一些字符串处理工具。

tmp <- readLines("spss1.txt")  ## read from .txt
tmp <- trimws(gsub("[A-Z/.]", "", tmp))  ## remove caps and specials
nm <- strsplit(tmp[[1]], " ")[[1]]  ## split names
tmp <- unlist(strsplit(tmp[3:11], "\s{2,}") )  ## split data blocks

最后,在空格处拆分得到结果。

dat <- setNames(
  type.convert(do.call(rbind.data.frame, strsplit(tmp, "\s"))), 
  nm)

结果

dat
#    gpid anx socskls assert
# 1     1   5       3      3
# 2     1   5       4      3
# 3     1   4       5      4
# 4     1   4       5      4
# 5     1   3       5      5
# 6     1   4       5      4
# 7     1   4       5      5
# 8     1   4       4      4
# 9     1   5       4      3
# 10    1   5       4      3
# 11    1   4       4      4
# 12    2   6       2      1
# 13    2   6       2      2
# 14    2   5       2      3
# 15    2   6       2      2
# 16    2   4       4      4
# 17    2   7       1      1
# 18    2   5       4      3
# 19    2   5       2      3
# 20    2   5       3      3
# 21    2   5       4      3
# 22    2   6       2      3
# 23    3   4       4      4
# 24    3   4       3      3
# 25    3   4       4      4
# 26    3   4       5      5
# 27    3   4       5      5
# 28    3   4       4      4
# 29    3   4       5      4
# 30    3   4       6      5
# 31    3   4       4      4
# 32    3   5       3      3
# 33    3   4       4      4

注意: 结果与 @emily-kothe 的方法相同。也许作者使用了不同的数据或者您的 manova 方法有缺陷?

如果我没理解错,数据集的第1、5、9、13列属于变量gpid,第2、6、10、14列属于变量anx , 等等。所以,我们需要

  • 从宽格式重塑为长格式
  • 具有多个测量变量
  • 其中每个度量变量跨越多个列
  • 并且缺少某些值。

条条大路通罗马。

这就是我使用我最喜欢的工具会做的事情。特别是,此方法使用 data.table::melt() 的功能同时重塑多个度量列。不需要在文本编辑器中手动清理数据部分。

生成的数据集 result 可以在 OP 请求的任何后续 R 代码中直接使用。使用.csv文件就不用绕路了(不过,可以随意将result保存为.csv文件)。

library(data.table)
library(magrittr)
cols <- c("gpid", "anx", "socskls", "assert")
raw <- fread(text = "
1 5 3 3     1 5 4 3     1 4 5 4     1 4 5 4
1 3 5 5     1 4 5 4     1 4 5 5     1 4 4 4
1 5 4 3     1 5 4 3     1 4 4 4
2 6 2 1     2 6 2 2     2 5 2 3     2 6 2 2
2 4 4 4     2 7 1 1     2 5 4 3     2 5 2 3
2 5 3 3     2 5 4 3     2 6 2 3
3 4 4 4     3 4 3 3     3 4 4 4     3 4 5 5
3 4 5 5     3 4 4 4     3 4 5 4     3 4 6 5
3 4 4 4     3 5 3 3     3 4 4 4",
fill = TRUE)
mv <- colnames(raw) %>% 
  matrix(ncol = 4L, byrow = TRUE) %>% 
  as.data.table() %>% 
  setnames(new = cols)
result <- melt(raw, measure.vars = mv, na.rm = TRUE)[
  order(rowid(variable))][
    , variable := NULL]
result
    gpid anx socskls assert
 1:    1   5       3      3
 2:    1   5       4      3
 3:    1   4       5      4
 4:    1   4       5      4
 5:    1   3       5      5
 6:    1   4       5      4
 7:    1   4       5      5
 8:    1   4       4      4
 9:    1   5       4      3
10:    1   5       4      3
11:    1   4       4      4
12:    2   6       2      1
13:    2   6       2      2
14:    2   5       2      3
15:    2   6       2      2
16:    2   4       4      4
17:    2   7       1      1
18:    2   5       4      3
19:    2   5       2      3
20:    2   5       3      3
21:    2   5       4      3
22:    2   6       2      3
23:    3   4       4      4
24:    3   4       3      3
25:    3   4       4      4
26:    3   4       5      5
27:    3   4       5      5
28:    3   4       4      4
29:    3   4       5      4
30:    3   4       6      5
31:    3   4       4      4
32:    3   5       3      3
33:    3   4       4      4
    gpid anx socskls assert

一些解释

fread() returns a data.table raw 默认列名 V1, V2, ... V16并用 NA

填充缺失值

mv是一个data.table,表示raw的哪些列属于每个目标变量:

mv
   gpid anx socskls assert
1:   V1  V2      V3     V4
2:   V5  V6      V7     V8
3:   V9 V10     V11    V12
4:  V13 V14     V15    V16

此信息由 melt() 使用。 melt() 还会从生成的长格式中删除具有缺失值的行。

整形后,行按可变编号排序,但需要使用 rowid(variable) 按原始行顺序重新排序。最后,删除 variable 列。

编辑:改进版本[​​=62=]

再想一想,这里是代码的简化版本,它跳过了 mv 的创建并使用了 data.table chaining:

library(data.table)
cols <- c("gpid", "anx", "socskls", "assert")
result <- fread(
  text = "
1 5 3 3     1 5 4 3     1 4 5 4     1 4 5 4
1 3 5 5     1 4 5 4     1 4 5 5     1 4 4 4
1 5 4 3     1 5 4 3     1 4 4 4
2 6 2 1     2 6 2 2     2 5 2 3     2 6 2 2
2 4 4 4     2 7 1 1     2 5 4 3     2 5 2 3
2 5 3 3     2 5 4 3     2 6 2 3
3 4 4 4     3 4 3 3     3 4 4 4     3 4 5 5
3 4 5 5     3 4 4 4     3 4 5 4     3 4 6 5
3 4 4 4     3 5 3 3     3 4 4 4",
  fill = TRUE, col.names = rep(cols, 4L))[
    , melt(.SD, measure.vars = patterns(cols), value.name = cols, na.rm = TRUE)][
      order(rowid(variable))][
        , variable := NULL][]
result

此处,在对 fread() 的调用中对列进行了重命名。在这种情况下,重复的列名是可取的(与通常的用例相反),因为 patterns() 函数在随后调用 melt() 时使用重复的列名来组合属于一个度量的列变量。