【问题标题】:Convert a small dataset written in SPSS to CSV将用 SPSS 编写的小数据集转换为 CSV
【发布时间】:2021-05-23 15:21:25
【问题描述】:

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

我想知道是否有办法将此数据转换为.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

【问题讨论】:

  • notepad++这样的文本编辑工具具有列选择类型功能,可以将4组列中的数据剪切和粘贴为1组。那么reader::read_table 可以完成剩下的工作。
  • 亲爱的 Eli-k,您能否复制page 191 of that book 上提供的 SPSS manova 表?

标签: r dataframe csv tidyverse spss


【解决方案1】:

如果我理解正确的话,数据集的第 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() 返回一个 data.table raw,其默认列名称为V1V2、...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 列被删除。

编辑:改进版

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

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() 的调用中被重命名。在这种情况下,重复的列名是可取的(与通常的用例相反),因为在随后对 melt() 的调用中的 patterns() 函数使用重复的列名来组合属于一个度量变量的列。

【讨论】:

    【解决方案2】:

    使用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 方法有缺陷?

    【讨论】:

      【解决方案3】:

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

      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 和 assert 值。而值 1、5、4、3 似乎在下一个SPSS 语法中粘贴数据的列(即从左到右读取语法的下 4 个值)实际上是参与者 10 的值。

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

      【讨论】:

        猜你喜欢
        • 2022-08-15
        • 1970-01-01
        • 2018-11-19
        • 2022-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-31
        相关资源
        最近更新 更多