已经好几天了,我已经遇到了R中的问题,尝试使用循环在数据帧中的多个因子列中创建重复级别。这是一个更大项目的一部分。
我有超过200个SPSS
数据集,其中案例数在4,000到23,000之间变化,变量数在120到1,200之间变化(其中一个SPSS
数据集的摘录{ {3}})。这些文件包含数字和因子变量,许多因子都有重复的级别。我已经使用外部包中的read.spss
将它们导入到数据框中,保留了值标签,因为我需要它们以供进一步使用。在导入期间,R警告我有关因子列中的重复级别:
> adn <- read.spss("/tmp/adn_110.sav", use.value.labels = TRUE,
use.missings = TRUE, to.data.frame = TRUE)
Warning messages:
1: In read.spss("/tmp/adn_110.sav", use.value.labels = TRUE, use.missings = TRUE, :
/tmp/adn_110.sav: Unrecognized record type 7, subtype 18 encountered in system file
2: In `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels) else paste0(labels, :
duplicated levels in factors are deprecated
3: In `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels) else paste0(labels, :
duplicated levels in factors are deprecated
数据框,导出为.RData
,can be found here。当我使用table
(例如)获取任何因子列的每个级别的计数时,将显示所有重复级别,但所有重复级别的计数将添加到重复级别的第一次出现并且对于所有级别返回其他0:
> table(adn[["adn01"]], useNA = "ifany")
Incorrect Incorrect Partially correct Partially correct
8 0 4 0
Correct <NA>
2 1
Warning message:
In `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels) else paste0(labels, :
duplicated levels in factors are deprecated
我知道在调用as.numeric
时我可以轻松地处理因子table
。但是,我需要输出中显示的级别名称。我可以使用make.unique
使各个因子列的级别唯一,在重复级别的末尾附加一个数字:
> levels(adn[["adn01"]]) <- make.unique(levels(adn[["adn01"]]), sep = " ")
像魅力一样工作。然后table
向我展示了正确的计数:
> table(adn[["adn01"]], useNA = "ifany")
Incorrect Incorrect 1 Partially correct
5 3 1
Partially correct 1 Correct <NA>
3 2 1
但是,对于200多个文件中的每一个中的每个因子列执行此操作,其中变量的数量在120和1,200之间变化,这将是一生的任务。如果文件发生变化,我将不得不重做所有内容。我天真地认为循环通过ccolums会很容易。但是,make.table
需要名称。我尝试过以下方法:
> lapply(adn[ , 1:length(adn)], make.unique(as.vector(attr(adn[ , 1:length(adn)],
"levels"))))
Error in make.unique(as.vector(attr(adn[, 1:length(adn)], "levels"))) :
'names' must be a character vector
没有运气。我在最后几天尝试了很多其他的东西,包括经典的for
循环。仍然相同:'names' must be a character vector
。我想问题是索引列的属性levels
,这是一个列表组件,但我无法弄清楚是什么。其他问题可能是并非所有列都是因素。有人可以帮忙吗?
修改
can be found here提供的解决方案完美无缺。再次感谢你!
答案 0 :(得分:1)
尝试
load('adn.RData')
indx <- sapply(adn, is.factor)
adn[indx] <- lapply(adn[indx], function(x) {
levels(x) <- make.unique(levels(x))
x })
table(adn[['adn01']], useNA='ifany')
# Incorrect Incorrect.1 Partially correct Partially correct.1
# 5 3 1 3
# Correct <NA>
# 2 1
table(adn[['adn03']], useNA='ifany')
# Incorrect Partially correct Correct <NA>
# 6 3 5 1
如果您有多个文件,可以将文件读入列表,然后在list
上进行处理。例如,考虑到文件位于工作目录中。
files <- list.files(pattern='^adn\\d+')
lst1 <- lapply(files, function(x) read.spss(x, use.value.labels = TRUE,
use.missings = TRUE, to.data.frame = TRUE) #not tested
出于测试目的,我使用相同的数据集lst1
创建adn
。
adn1 <- adn
lst1 <- list(adn, adn1)
现在,您为每个make.unique
元素应用list
lst2 <- lapply(lst1, function(dat) {
indx <- sapply(dat, is.factor)
dat[indx] <- lapply(dat[indx], function(x){
levels(x) <- make.unique(levels(x))
x})
dat})
lapply(lst2, function(x) table(x[['adn01']], useNA='ifany'))
# [[1]]
# Incorrect Incorrect.1 Partially correct Partially correct.1
# 5 3 1 3
# Correct <NA>
# 2 1
# [[2]]
# Incorrect Incorrect.1 Partially correct Partially correct.1
# 5 3 1 3
# Correct <NA>
# 2 1