0

我一直在尝试运行MSCMT::listFromLong命令将数据框从长格式转换为列表。我确信我的数据是长格式的,但是每当我运行代码时,我都会遇到以下错误

Error in order(rownames(res[[i]])) : argument 1 is not a vector

查看listFromLong源代码后,我意识到错误一定是在这段代码中** **之间的某处:

> listFromLong <- function(foo, unit.variable, time.variable, 
>                          unit.names.variable=NULL,exclude.columns=NULL) {  
> if(!is.data.frame(foo)) stop("foo must be a data.frame")
> 
>   # main helper function   DFtoList <-
> function(input,rowcol,colcol,colnamecol=NULL,exclude=NULL) {
>     stopifnot(length(dim(input))==2)
>     datcols    <- setdiff(seq_len(ncol(input)), 
>                           c(rowcol,colcol,colnamecol,exclude))
>     *res        <- vector("list",length(datcols))*
>     names(res) <- if (!is.null(colnames(input))) colnames(input)[datcols] else 
>                                                  as.character(datcols)
>     if (!is.null(colnamecol)) {
>       c2n        <- na.omit(unique(input[,colnamecol]))
>       names(c2n) <- na.omit(unique(input[,colcol]))
>     }  
>     for (i in seq_along(res)) {
>       idx  <- !is.na(input[,datcols[i]])
>       rown <- unique(input[idx,rowcol])
>       coln <- unique(input[idx,colcol])
>       res[[i]] <- matrix(NA,nrow=length(rown),ncol=length(coln))
>       rownames(res[[i]]) <- rown
>       colnames(res[[i]]) <- coln
>       for (j in which(idx)) 
>         res[[i]][as.character(input[j,rowcol]),as.character(input[j,colcol])]
> <- 
>           input[j,datcols[i]]
>       **if (!is.null(colnamecol)) colnames(res[[i]]) <- c2n[as.character(coln)]**
> **      res[[i]] <- res[[i]][order(rownames(res[[i]])),,drop=FALSE]**
>     }
>     res   }

我无法确定错误的确切来源,因为据我了解,数据已准备好由此代码处理。如果有人能告诉我如何找到“参数 1”,或者解释为什么它没有转换为 ** ** 之间的行中的向量,我将不胜感激。

我的数据是使用从 Stata 导入的

data <- readstata13::read.dta13("path/data.dta") 
4

1 回答 1

0

我不确定错误发生在哪里,但据我所知,该函数基本上将沿着索引“regionname”的数据拆分为使用“year”作为行名的矩阵。之后,它会转置一些东西,以便有一个原始列的矩阵列表,列中有现在的国家。

我们可以使用 an 做同样的非常简单的array事情,使用 相应地对其进行转置,最后使用来自@flodel's answeraperm转换为一个列表。 例子:split.along.dim()

data(basque, package="Synth")
B <- split.along.dim(aperm(simplify2array(by(basque, basque$regionname, function(x) {
  `rownames<-`(as.matrix(x[,!names(x) %in% c("regionno", "regionname", "year")]),
               x[,"year"])})), c(1, 3, 2)), 3)

使用您的原始数据,您只需替换数据和列名。

现在让我们检查结果是否等于MSCMT::listFromLong.

Basque <- MSCMT::listFromLong(basque, unit.variable="regionno", 
                              time.variable="year", 
                              unit.names.variable="regionname")

奇怪的是,MSCMT::listFromLong用 s 删除列表元素的所有行NA,但让我们这样做......

B <- lapply(B, function(x) x[apply(x, 1, function(x) !all(is.na(x))), ])

我们B的列按字母顺序排序,我们使用Basque进行排序。

Basque <- lapply(Basque, function(x) x[, order(colnames(x))])

现在检查,

all.equal(Basque, B)
# [1] TRUE

等等!


@flodel的 answer 的函数,将数组转换为列表:

split.along.dim <- function(a, n) {
  setNames(lapply(split(a, arrayInd(seq_along(a), dim(a))[, n]),
                  array, dim = dim(a)[-n], dimnames(a)[-n]),
           dimnames(a)[[n]])
}
于 2021-01-15T05:24:25.247 回答