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

时间:2018-02-10 02:46:25

标签: r class boxplot factors coercion

试图弄清楚因子/数据框的强制如何在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 df:数据框,df$x:数字,df$c:因素(因为我们将c发送到数据框中)和is.data.frame is.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"

现在,我使用x中存在的因子绘制c的分布图。所以第一个参数是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 即,我们仍然在箱图的x轴上有3个类别,尽管可以分为两类。

因此,我找到的一个解决方案是将df变量的类更改为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 version 的问题:

  • R中是否所有dataframeslists

  • 为什么我们的箱形图在第二种情况下丢失了x3(当我们将class(df)强制转换为numericcharacter时?

  • 如果我们通过执行上述步骤将因素强制转换为字符,为什么仍然显示变量的类是factor

  • 为什么df在我们完成上述步骤后仍然不再是dataframe

2 个答案:

答案 0 :(得分:0)

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

  

是否所有数据框都列在R?

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

  

为什么在我们完成上述步骤后df不再是一个列表?

它没有。它不再是数据框,因为您使用class(df)<- c("numeric", "character")更改了类。 is.list(df)仍然返回TRUE。

  

如果我们通过执行上述步骤将因素强制转换为字符,为什么仍然显示变量的类是因子?

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

  

为什么我们的boxplot在第二种情况下掉落了x3(当我们将类(df)强制转换为数字和字符时?

您通过将对象的class属性显式设置为向量c("numeric", "character")来搞乱数据框对象。很难预测这种情况的全部影响。我最好的猜测是,boxplot或绘制轴的函数以某种方式访问​​数据框的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)

答案 1 :(得分:0)

像这样使用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 = .)

screenshot