我一直在努力解决以下问题,因为我需要尽快加载,操作并从新数据集中生成分数。我已经定义了一个数据字典,其中包含每个变量类的描述(例如数字,因子,字符,日期),以及适用的所有可能因子级别的列表:
DD <- data.frame(Var = c("a", "b", "c", "d"),
Class = c("Numeric", "Factor", "Factor", "Date"),
Levels = c(NA, "B1, B2, B3", "C1, C2", NA))
Data <- data.frame(a = 5, b = "B1", c = "C2", d = "2015-05-01")
最终,我打算使用model.matrix来生成一个设计矩阵,其中包含一组通用的指标变量/列,而不管在特定数据集中观察到的实际因子水平,因此我可以准确地从模型中获取数据。
我需要尽快完成这些任务,因此,我试图找到一种避免使用lapply / loops的解决方案。这是(一个稍微复杂的版本)我现有的设置因子水平的解决方案,目前对我的要求来说太慢了:
lapply(1:ncol(Data[,DD$Class=="Factor"]), function(i) {
factor( as.character( unlist( Data[,DD$Class=="Factor"][i])) ,
levels = unlist(strsplit(as.character(DD$Levels[DD$Class=="Factor"][i]), ", ")) )
})
任何有关避免在此处使用循环的建议,如果可能的话,或任何其他解决方案将非常感谢!
谢谢!
答案 0 :(得分:1)
将级别存储为需要解析的单个字符串是低效的。我建议使用一个列表并将这些级别直接存储为字符向量。
DD <- list(a = list(class="numeric"),
b = list(class="factor", levels = c("B1", "B2", "B3")),
c = list(class="factor", levels = c("C1", "C2")),
b = list(class="Date"))
您不需要“解构”您的因素来添加新级别。
示例:
fac <- factor(c("a", "b", "a"))
# two levels
factor(fac, letters)
# 26 levels, data has not changed
我不知道如何在这里避免“循环”,但是lapply是执行循环的有效方式,我怀疑这是性能瓶颈。使用备注1和2,您可以编写更高效的内部函数。抛弃data.frame以获取data.table或tbl也可能有用。
答案 1 :(得分:0)
您可以在创建数据框时定义列类(以及因子的级别):
mylevels <- c("b1","b2","b3","c1","c2")
myData <- data.frame(a =
numeric(), b = factor(levels=mylevels), c = factor(levels=mylevels), d
= character())
这将创建一个空白数据框,您可以稍后填写。
回复您的评论:只有当 myData 与数据具有相同的列类时,rbind才有效。否则列类将更改。我的观点是:如果您加载的数据相似(具有相同的列数,列具有相同的名称等),那么您可以在加载数据时正确设置类,如:
myclasses <- c(“numeric”,”factor”,”factor”,”date”)
myData <- read.table(“mydatafile.csv”, sep=”,”, header = TRUE, colClasses = myclasses)
myLevels <- c(“a1”,”a2”,”b1”,”b2”)
myfactorlist <- c(“b”,”c”)
levels(myData[,myfactorlist]) <- myLevels
这里我假设您的列名称与前面的示例相同:“a”,“b”,“c”,“d”,其中&#34; c&#34;和&#34; b&#34;是因子列。
答案 2 :(得分:0)
你将对列进行迭代,但可以像这样以更清洁的方式完成。我们假设您要保留输入数据框,因此我们创建一个新的数据框Data2
来保存结果。请注意,我们已将DD
字符的列设置为而不是因子。 Data
来自问题。
DD <- data.frame(Var = c("a", "b", "c", "d"),
Class = c("Numeric", "Factor", "Factor", "Date"),
Levels = c(NA, "B1, B2, B3", "C1, C2", NA), stringsAsFactors = FALSE)
Data2 <- Data
# factors
Factors <- subset(DD, Class == "Factor")
Levels <- strsplit(as.character(Factors$Levels), ", ")
Data2[Factors$Var] <- Map(factor, Data2[Factors$Var], Levels)
# dates
Dates <- subset(DD, Class == "Date")
Data2[Dates$Var] <- Map(as.Date, Data2[Dates$Var])
,并提供:
> str(Data2)
'data.frame': 1 obs. of 4 variables:
$ a: num 5
$ b: Factor w/ 3 levels "B1","B2","B3": 1
$ c: Factor w/ 2 levels "C1","C2": 2
$ d: Date, format: "2015-05-01"