将数据框列转换为带索引的因子

时间:2017-08-16 12:24:55

标签: r dataframe indexing types

我把一些结果放在数据框中。我有一些因子列和许多数字列。根据{{​​3}}问题的答案,我可以轻松地将数字列转换为带索引的数字。

#create example data
df = data.frame(replicate(1000,sample(1:10,1000,rep=TRUE)))
df$X1 = LETTERS[df$X1]
df$X2 = LETTERS[df$X2]
df$X3 = LETTERS[df$X3]
df[-1] <- sapply(df[-1], function(x) ifelse(runif(length(x)) < 0.1, NA, x))

#find columns that are factors
factornames = c("X1", "X2", "X3")
factorfilt = names(df) %in% factornames

#convert non-factor columns to numeric
df[, !factorfilt] = as.numeric(as.character(unlist(df[, !factorfilt])))

但是当我想为我的因子列做同样的事情时,我无法获得相同的索引:

#convert factor columns to factor
df[, factorfilt] = as.factor(as.character(unlist(df[, factorfilt])))
class(df$X1)

[1] "character"

df[, factorfilt] = as.factor(as.character(df[, factorfilt]))
class(df$X1)

[1] "character"

df[, factorfilt] = as.factor(unlist(df[, factorfilt]))
class(df$X1)

[1] "character"

df[, factorfilt] = as.factor(df[, factorfilt]) 

Error in sort.list(y) : 'x' must be atomic for 'sort.list'
Have you called 'sort' on a list?

如果我致电"character",则所有这些都会返回class(df$X1),而如果我运行df$X1= as.factor(df$X1),则会返回"factor"

为什么在我拨打as.factor时,这种方式的索引不起作用,但如果我拨打as.numeric会这样做吗?

1 个答案:

答案 0 :(得分:2)

你应该观察一些你正在做的事情的行为方面。像你一样定义你的数据:

df = data.frame(replicate(1000,sample(1:10,1000,rep=TRUE)))
df$X1 = LETTERS[df$X1]
df$X2 = LETTERS[df$X2]
df$X3 = LETTERS[df$X3]
df[-1] <- sapply(df[-1], function(x) ifelse(runif(length(x)) < 0.1, NA, x))

factornames = c("X1", "X2", "X3")
factorfilt = names(df) %in% factornames
df[, !factorfilt] = as.numeric(as.character(unlist(df[, !factorfilt])))

现在让我们看一下制作X1X2X3因素的结果,但不要重新分配。

test <- as.factor(as.character(df[, factorfilt]))
class(test) # "factor"
length(test) # 3

这里要注意的重要一点是test 不是数据框。它是一个向量,您试图保存数据帧的三列。我认为我们应该质疑将数据帧转换为矢量以存储在数据帧中的智慧。

然后考虑你的第二个任务:

test2 <- as.factor(as.character(unlist(df[, factorfilt])))
class(test2) # factor
length(test2) # 3000

同样,这是一个因素,但它的长度与test完全不同。通过让你将它重新分配回df,R只是这样,并且只是因为它认识到它可以调和维度。但是,当您尝试将因子推入X1X2X3时,对于如何处理因子水平存在一个很大的问题。所有三个变量都应该具有相同的水平吗?每个变量是否只有其自身的水平? R不是试图宣布“适当的”选择是什么,而是忽略它并将其转换回一个角色供你自己处理。

以这种方式操纵列的事实有可能意外地改变类是不这样做的一个很好的理由。这在您NA的分配中很明显。让我们再看一遍:

df = data.frame(replicate(1000,sample(1:10,1000,rep=TRUE)))
df$X1 = LETTERS[df$X1]
df$X2 = LETTERS[df$X2]
df$X3 = LETTERS[df$X3]

此时,X4X1000都是integer类列。当你运行

df[-1] <- sapply(df[-1], function(x) ifelse(runif(length(x)) < 0.1, NA, x))

它们现在都是character,您继续将它们转换为numeric。他们不再是原来的班级了。

相反,如果我们使用lapply

df[-1] <- lapply(df[-1], function(x) ifelse(runif(length(x)) < 0.1, NA, x))

原始类被保留,不需要将它们转换回数字类。同样,我们可以轻松地将X1转换为X3到具有

的因子
df[, factorfilt] <- lapply(df[, factorfilt], as.factor)

作为一般规则,最好将列中的数据作为不同的列进行操作。一旦开始在多个列上分配单个向量,就会进入恶作剧的黑暗世界。