在 r 中的函数内部使用 assign 时是否可以保留数据类型?
Is it possible to keep the datatype while using assign inside a function in r?
我第一次 post 在这里,如果我遗漏了任何重要信息,请告诉我。
我正在处理大量时间形式的数据(1:30=rowID)与存储在多个数据帧中的值,我需要将其保存为 data.frame。
我写了一个函数,它从我的全局环境中获取数据框,并根据它们的值将每个集合中的列排序到新的数据框中。
所以我从我的数据框的名称列表开始作为我的函数的输入,然后在使用分配函数时将创建的新数据框分配到我的全局环境结束。
我得到的所有数据框都是 30 行长,但列长不同,具体取决于案例在数据集中出现的频率。每个dataframe的名称代表一个数据集,里面的列名代表一个时间线。我使用数据框,所以我不会丢失列名的信息。
这适用于 0 个案例和大于 1 的所有案例。
但是,如果 data.frame 最终只有一列并且我使用分配函数,它在我的全局环境中显示为矢量而不是数据框。因此,我丢失了列的名称,我的其他仅使用数据帧的函数在这种情况下停止并抛出错误。
这是我的问题的一个基本示例:
#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. 或者有没有我可以使用的替代函数来代替 assign()?如果我使用 <<- 我怎样才能像上面那样分配名称?
子集化时可以使用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 ...
现在,综上所述,我同意 Roland 的评论——您几乎不想采用这种以复杂方式分配给全局环境的方法,而应该 return 一个列表;这是最佳实践。但是,您仍然需要 drop = FALSE
来保留列名。
真的,对我来说,可能有一种 完全不同的 方法来做你想做的任何类型的数据争论,这是一种更好的方法。我只是没有很好地掌握你的任务来提出建议。
我第一次 post 在这里,如果我遗漏了任何重要信息,请告诉我。
我正在处理大量时间形式的数据(1:30=rowID)与存储在多个数据帧中的值,我需要将其保存为 data.frame。 我写了一个函数,它从我的全局环境中获取数据框,并根据它们的值将每个集合中的列排序到新的数据框中。
所以我从我的数据框的名称列表开始作为我的函数的输入,然后在使用分配函数时将创建的新数据框分配到我的全局环境结束。 我得到的所有数据框都是 30 行长,但列长不同,具体取决于案例在数据集中出现的频率。每个dataframe的名称代表一个数据集,里面的列名代表一个时间线。我使用数据框,所以我不会丢失列名的信息。
这适用于 0 个案例和大于 1 的所有案例。 但是,如果 data.frame 最终只有一列并且我使用分配函数,它在我的全局环境中显示为矢量而不是数据框。因此,我丢失了列的名称,我的其他仅使用数据帧的函数在这种情况下停止并抛出错误。
这是我的问题的一个基本示例:
#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. 或者有没有我可以使用的替代函数来代替 assign()?如果我使用 <<- 我怎样才能像上面那样分配名称?
子集化时可以使用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 ...
现在,综上所述,我同意 Roland 的评论——您几乎不想采用这种以复杂方式分配给全局环境的方法,而应该 return 一个列表;这是最佳实践。但是,您仍然需要 drop = FALSE
来保留列名。
真的,对我来说,可能有一种 完全不同的 方法来做你想做的任何类型的数据争论,这是一种更好的方法。我只是没有很好地掌握你的任务来提出建议。