在r中的函数内部使用assign时是否可以保留数据类型?

问题描述 投票:0回答:1

我在这里的第一篇文章,所以请告诉我是否缺少任何重要信息。

我正在处理大量以时间(1:30 = rowID)vs值的形式存储的数据,这些数据全部存储在多个数据帧中,我需要将其保留为data.frame。我编写了一个函数,该函数从全局环境中获取数据帧,并根据它们的值将每个集中的列排序为新的数据帧。

因此,我首先从数据帧的名称列表作为函数输入,然后在使用assign函数的同时,将创建的新数据帧分配给全局环境。我得到的所有数据框长30行,但列长度不同,具体取决于案例在数据集中出现的频率。每个数据框的名称表示一个数据集,而内部的列名称表示一个时间轴。我使用数据框,因此不会丢失列名称的信息。

[这适用于0个案例以及大于1的所有案例。但是,如果data.frame仅以一列结尾,而我使用了assign函数,则它将在我的全局环境中显示为向量,而不是数据帧。因此,我松开了列的名称,而其他仅使用数据帧的函数在这种情况下停止并抛出错误。

这是我的问题的基本示例:

#create two datasets with different cases
data1 <- data.frame(matrix(nrow=30, ncol=5))
data1[1] <- c(rep(1,each=30))
data1[2] <- c(rep(5, each=30))
data1[3] <- c(rep(5, each=30))
data1[4] <- c(rep(10, each=30))
data1[5] <- c(rep(10, each=30))

data2 <- data.frame(matrix(nrow=30, ncol=6))
data2[1] <- c(rep(5,each=30))
data2[2] <- c(rep(1, each=30))
data2[3] <- c(rep(1, each=30))
data2[4] <- c(rep(0, each=30))
data2[5] <- c(rep(0, each=30))
data2[6] <- c(rep(10, each=30))

#create list with names of datasets
names <- c('data1','data2')

#function for sorting
examplefunction <- function(VarNames) {
  for (i in 1:length(VarNames)) {
    #get current dataset
    name <- VarNames[i]
    data <- get(VarNames[i])

    #create new empty data.frames for sorting
    data.0 <- data.frame(matrix(nrow=30))
    name.data.0 <- paste(name,"0", sep=".")
    c.0 = 2 #start at second column, since first doesn't like the colname later
    data.1 <- data.frame(matrix(nrow=30))
    name.data.1 <- paste(name,"1", sep=".")
    c.1 = 2
    data.5 <- data.frame(matrix(nrow=30))
    name.data.5 <- paste(name,"5", sep=".")
    c.5 = 2
    data.10 <- data.frame(matrix(nrow=30))
    name.data.10 <- paste(name,"10", sep=".")
    c.10 = 2

    #sort data into new different data.frames
    for (c in 1:ncol(data)) {

      if(data[1,c]==0) {
        data.0[c.0] = data[c]
        c.0 = c.0 +1
      }
      else if(data[1,c]==1) {
        data.1[c.1] = data[c]
        c.1 = c.1 +1
      }
      else if(data[1,c]==5) {
        data.5[c.5] = data[c]
        c.5 = c.5 +1
      }
      else if(data[1,c]==10) {
        data.10[c.10] = data[c]
        c.10 = c.10 +1
      }
      else (stop="new values")
    }

    #remove first column with weird name
    data.0 <- data.0[,-1] 
    data.1 <- data.1[,-1] 
    data.5 <- data.5[,-1] 
    data.10 <- data.10[,-1] 

    #assign data frames to global environment
    assign(name.data.0, data.0, envir = .GlobalEnv)
    assign(name.data.1, data.1, envir = .GlobalEnv)
    assign(name.data.5, data.5, envir = .GlobalEnv)
    assign(name.data.10, data.10, envir = .GlobalEnv)

  }
}

#function call
examplefunction(names)

如前所述,如果运行此命令,最终将得到0个变量和> 1个变量的数据帧。还有三个向量,其中数据帧只有一列。

所以我的问题是:1.有什么方法可以保留数据类型并强制R将其分配给数据帧而不是向量?2.还是有替代我可以使用的替代函数?如果使用<

r function dataframe types assign
1个回答
0
投票

子设定时可以使用drop = FALSE

examplefunction <- function(VarNames) {
    for (i in 1:length(VarNames)) {
        #get current dataset
        name <- VarNames[i]
        data <- get(VarNames[i])

        #create new empty data.frames for sorting
        data.0 <- data.frame(matrix(nrow=30))
        name.data.0 <- paste(name,"0", sep=".")
        c.0 = 2 #start at second column, since first doesn't like the colname later
        data.1 <- data.frame(matrix(nrow=30))
        name.data.1 <- paste(name,"1", sep=".")
        c.1 = 2
        data.5 <- data.frame(matrix(nrow=30))
        name.data.5 <- paste(name,"5", sep=".")
        c.5 = 2
        data.10 <- data.frame(matrix(nrow=30))
        name.data.10 <- paste(name,"10", sep=".")
        c.10 = 2

        #sort data into new different data.frames
        for (c in 1:ncol(data)) {

            if(data[1,c]==0) {
                data.0[c.0] = data[c]
                c.0 = c.0 +1
            }
            else if(data[1,c]==1) {
                data.1[c.1] = data[c]
                c.1 = c.1 +1
            }
            else if(data[1,c]==5) {
                data.5[c.5] = data[c]
                c.5 = c.5 +1
            }
            else if(data[1,c]==10) {
                data.10[c.10] = data[c]
                c.10 = c.10 +1
            }
            else (stop="new values")
        }

        #remove first column with weird name
        data.0  <- data.0[ , -1, drop = FALSE]
        data.1  <- data.1[ , -1, drop = FALSE]
        data.5  <- data.5[ , -1, drop = FALSE]
        data.10 <- data.10[ , -1, drop = FALSE] 

        #assign data frames to global environment
        assign(name.data.0,  data.0,  envir = .GlobalEnv)
        assign(name.data.1,  data.1,  envir = .GlobalEnv)
        assign(name.data.5,  data.5,  envir = .GlobalEnv)
        assign(name.data.10, data.10, envir = .GlobalEnv)

    }
}

#function call
examplefunction(names)

让我们看一下单列数据框:

str(data1.1)
'data.frame':   30 obs. of  1 variable:
  $ X1: num  1 1 1 1 1 1 1 1 1 1 ...
str(data2.10)
'data.frame':   30 obs. of  1 variable:
  $ X6: num  10 10 10 10 10 10 10 10 10 10 ...

现在,所有这些,我都同意罗兰的评论-您几乎从不希望采用这种以复杂的方式分配给全球环境的方法,而应该返回一个列表;这是最佳做法。但是,您仍然需要drop = FALSE保留列名。实际上,对我来说,可能有一种[[完全不同]]方法来处理您想要进行的任何类型的数据整理,这是一种更好的方法。我只是不太了解您的建议工作。

© www.soinside.com 2019 - 2024. All rights reserved.