融合数组并使数值成为字符

时间:2016-11-14 11:34:58

标签: arrays r data.table melt

我有一个数组,我想基于dimnames融化它。问题是维度名称是大数字值,因此将它们转换为错误的ID会将它们转换为示例:

test <- array(1:18, dim = c(3,3,2), dimnames = list(c(00901291282245454545454,329293929929292,2929992929922929),
                                                   c("a", "b", "c"),
                                                   c("d", "e")))

library(reshape2)
library(data.table)
test2 <- data.table(melt(test))
test2[, Var1 := as.character(Var1)]

> test2
Var1 Var2 Var3 value
1: 9.01291282245455e+20    a    d     1
2:      329293929929292    a    d     2
3:     2929992929922929    a    d     3
4: 9.01291282245455e+20    b    d     4
5:      329293929929292    b    d     5
6:     2929992929922929    b    d     6
7: 9.01291282245455e+20    c    d     7
8:      329293929929292    c    d     8
9:     2929992929922929    c    d     9
10: 9.01291282245455e+20    a    e    10
11:      329293929929292    a    e    11
12:     2929992929922929    a    e    12
13: 9.01291282245455e+20    b    e    13
14:      329293929929292    b    e    14
15:     2929992929922929    b    e    15
16: 9.01291282245455e+20    c    e    16
17:      329293929929292    c    e    17
18:     2929992929922929    c    e    18

如何使用大ID字符创建第一列?我目前正在做的是将一个字母字母粘贴到dimnames然后融化,使其成为一个字符然后采用子字符串,这实在是效率低下。重要的是它是一种有效的解决方案,因为数据集是数百万行。有两个问题,如果它们位于ID前面,则会删除0,并将其转换为e + 20字符。

1 个答案:

答案 0 :(得分:2)

您需要将您的dimnames定义为character,然后轻轻修改melt.arraymelt时调用的array

test <- array(1:18, dim = c(3,3,2), dimnames = list(c("00901291282245454545454", "329293929929292", "2929992929922929"),
                                                    c("a", "b", "c"),
                                                    c("d", "e")))

自定义melt.array以添加一个参数,该参数允许您决定是否需要转换:

melt.array2 <- function (data, varnames = names(dimnames(data)), conv=TRUE, ...) 
{
    values <- as.vector(data)
    dn <- dimnames(data)
    if (is.null(dn)) 
        dn <- vector("list", length(dim(data)))
    dn_missing <- sapply(dn, is.null)
    dn[dn_missing] <- lapply(dim(data), function(x) 1:x)[dn_missing]
    if(conv){ # conv is the new parameter to know if conversion needs to be done
        char <- sapply(dn, is.character)
        dn[char] <- lapply(dn[char], type.convert)
    }
    indices <- do.call(expand.grid, dn)
    names(indices) <- varnames
    data.frame(indices, value = values)
}

尝试使用示例的新功能(使用conv=FALSE):

head(melt.array2(test, conv=FALSE))
                        # X1 X2 X3 value
# 1  00901291282245454545454  a  d     1
# 2          329293929929292  a  d     2
# 3         2929992929922929  a  d     3
# 4  00901291282245454545454  b  d     4
# 5          329293929929292  b  d     5
# 6         2929992929922929  b  d     6

编辑

reshape2devtools::install_github("hadley/reshape")的开发版本中,melt.array的定义不同,您可以使用参数as.is来避免转换:

melt(test, as.is=TRUE)

将为您提供与上述相同的结果(使用Var1等而不是X1等。