了解将因子强制转换为 R 数据帧中的字符

Understanding coercion of factors into characters in an R dataframe

试图弄清楚因子/数据框的强制转换在 R 中是如何工作的。我正在尝试为数据框的一个子集绘制箱线图。一步步来看

x = rnorm(30, 1, 1)

创建了一个具有正态分布的向量 x

c = c(rep("x1",10), rep("x2",10), rep("x3",10))

创建了一个字符串,稍后用作绘制 x1、x2、x3 箱线图的一个因素

df = data.frame(x,c)

将 x 和 c 合并为 data.frame。所以现在我们期望 class of df: dataframe, df$x: numeric, df$c: factor(因为我们将 c 发送到数据帧中)和 is.data.frameis.list 应用于 df 应该给我们 TRUETRUE。 (我假设所有数据帧也是列表?这就是为什么我们得到两个检查的 TRUE。)

这就是下面发生的事情。到现在都还好。

class(df)
#[1] "data.frame"
is.data.frame(df)
#[1] TRUE
is.list(df)
#[1] TRUE
class(df$x)
#[1] "numeric"
class(df$c)
#[1] "factor"

现在我使用 c 中存在的因素对 x 的分布进行了分组。所以第一个参数是x ~ c。但我只需要两个因素的箱线图:x1x2。所以我在 boxplot 函数中使用了一个 subset 参数。

boxplot(x ~ c, subset=c %in% c("x1", "x2"), data=df)

This is the plot we get, notice since x3 is a factor, it is still plotted 即尽管子集化为 2 个类别,我们在箱线图的 x 轴上仍然有 3 个类别。

所以,我找到的一个解决方案是将 df 变量的 class 更改为 numericcharacter

class(df)<- c("numeric", "character")

boxplot(x ~ c, subset=c %in% c("x1", "x2"), data=df)

New boxplot. This is what we wanted, so it worked!, we plotted boxes for just x1 and x2, got rid of x3

但是如果我们只是 运行 相同的检查,我们 运行 在对所有变量进行强制转换之前,我们会得到这些输出。

有什么好玩的吗?

class(df)
#[1] "numeric"   "character"
is.data.frame(df)
#[1] FALSE
is.list(df)
#[1] TRUE
class(df$x)
#[1] "numeric"
class(df$c)
#[1] "factor"

检查 df $ c(包含 caegories x1、x2、x3 的第二个变量)仍然是一个因子!

并且 df 不再是 list(所以它曾经是一个列表吗?)

如果不更改 df $ c 的数据类型,我们通过 class(df)<- c("numeric", "character") 这种强制转换究竟做了什么?

综上所述,

我对 tldr 版本的问题

如果我们以不同的顺序回答您的问题,答案会更有意义。

Are all dataframes, also lists in R?

是的。数据框是向量列表(列)。

And why did df stopped being a list after we did the above steps?

没有。它不再是数据框,因为您将 class 更改为 class(df)<- c("numeric", "character")is.list(df) returns 仍然正确。

If we did coerce factor into characters by doing the above steps, why is still showing that variable's class is factor?

class(df)df 对象本身进行操作,而不是对列进行操作。看看str(df)。因子列仍然是一个因子。 class(df) 将数据框对象本身的 class 属性设置为矢量。

Why did our boxplot dropped x3 in the 2nd case (when we coerced class(df) into numeric and character?

您通过将对象的 class 属性显式设置为向量 c("numeric", "character") 搞乱了数据框对象。很难预测其全部影响。我最好的猜测是箱线图或绘制轴的函数以某种方式访问​​了数据框的 class 属性。

做你真正想做的事:

x = rnorm(30, 1, 1)
c = c(rep("x1",10), rep("x2",10), rep("x3",10))
df = data.frame(x,c)
df$c <- as.character(df$c)

x = rnorm(30, 1, 1)
c = c(rep("x1",10), rep("x2",10), rep("x3",10))
df = data.frame(x,c, stringsAsFactors=FALSE)

像这样使用droplevels

df0 <- subset(df, c %in% c("x1", "x2"))
df0 <- transform(df0, c = droplevels(c))
levels(df0$c)
## [1] "x1" "x2"

请注意,现在 c 只有两个级别,而不是三个级别。

我们可以像这样使用 magrittr 将其写成管道:

library(magrittr)

df %>%
   subset(c %in% c("x1", "x2")) %>%
   transform(c = droplevels(c)) %>%
   boxplot(x ~ c, data = .)