小技巧--对常用的三种数据类型进行转换(数值型、字符型和因子型)。为什么要了解数据结构之间的差异和做对应转换呢?通常在画图和做分析时,不同情况对数据类型需求不一样,特别是新手在学习代码的时候,如果不清楚数据结构很容易造成错误。针对不同情况,根据自己的需求调整对应的数据类型,这样有助于我们更好地学习和运行code。通常所有的数据我们统称为向量,针对不同数据集结构(这里可以参考我们以前发表的推文:【R分享|实战】 新手福利~认识数据集的内在),主要可分为两类向量。一是,原子向量;二是,递归向量。我们可以借助下面这张图(黄师兄的总结)来理解:也就是说,原子向量主要包括:logical,integer, double, character等类型,其中integer和double统称为numeric(数值型向量)。而列表通常被称为递归向量,因为它可以包含其他列表。  针对这部分内容,以代码的形式给大家分享和讲解,希望能帮助大家少走弯路。首先,我们先构造数据集,并解读数据集中不同的数据类型:# 不同数据类型之间的差异与转换 -------------------------- # 随机构造数据集 year <- rep(2000:2021, 2) treatment <- rep(c("ck","treat"), each = 22) type <- factor(rep(c("a","b","c","d"), each = 11)) value1 <- sample(1:50, 44) value2 <- round(runif(44, min = 0, max = 1), 3) set.seed(111) value3 <- sample(c("1","1.5","2.5","3.5","4.5","5"), 44, replace = T) set.seed(111) value4 <- sample(c(1,1.5,2.5,3.5,4.5,5), 44, replace = T) # 打包数据集 dat <- data.frame(treatment, type, year, value1, value2, value3, value4) # 查看数据结构 str(dat) # 从查询的结果来看,treatment这个变量是字符型-“cha”向量; # type为因子型向量(factor)w/4表示有4个因子 # year是整数-“int”数值型向量;value1与year是同样类型的数值; # value2是数值型向量;value3是字符型;value4是与v3相同值的数值型变量。
上述code的结果:
 然后,我们分别以绘图和跑模型的方式对其差异进行讲解:# 以画图为例进行不同数据类型变量的讲解: library(ggplot2) ggplot(data = dat, aes(x = year, y = value1, color=treatment))+ geom_point()+ geom_line()+ labs(x="year") # 从图来看,由于year是数值型变量,画图时候会默认成连续型的所以会有间隔
# 这里我们将year改成因子型变量再对其进行展示: ggplot(dat, aes(as.factor(year), value1, color=treatment))+ geom_point()+ # geom_line()+ geom_path(group=treatment)+ labs(x="year") # 由于对x的变量进行了因子型转换,这个地方也是大家比较容易出错的。 # 对变量进行因子转化后,geom_line函数不能识别分组; # 因此利用geom_path函数的分组进行绘制。


从两张图来看,结果似乎差异不大,仅仅在x轴的label上出现了差异。图1为数值型的x轴是连续的,默认为数值,并不是实际的年份,所以会出现0.5这样的年份表达。 如果,我们将y轴用字符型的数据进行绘图,会有怎么的差异:
# 如果我们使用字符型作为我们的x轴和y轴,看看结果如何; ggplot(dat, aes(treatment, value3, fill = type))+ geom_bar(stat = "identity", position = "dodge")
# 用相同的数值,但是不同的数据类型y,比较两者差异 ggplot(dat, aes(treatment, value4, fill = type))+ geom_bar(stat = "identity", position = "dodge")


从两个结果来看,存在明显差异。如果是数值型向量,柱状图会默认展示一个总的柱状图;而如果是字符型向量,可以把每一个值都看作是个体,展示所有的情况。 接下来,我们从模型方面来理解,这里以最简单的线性模型为例:# 如果自变量为数值型 fit1 <- lm(value1 ~ year, data=dat) summary(fit1)
# 如果自变量为因子型 fit2 <- lm(value1~ as.factor(year), data=dat) summary(fit2)
# 如果自变量为字符型 fit3 <- lm(value1~ as.character(year), data=dat) summary(fit3)
当自变量为数值型时: 

当自变量为字符型时:

从这里可以看出当自变量为因子型或者字符型时,会将每个年份都作为一个个体与因变量做拟;而数值型是一个总体。并且,需要考虑当用其他更加复杂的模型,如果是字符型或因子型会延长模型的计算时间。特别是混合效应模型。 最后,我们可以根据自己的需要对三种数据类型之间进行转换:# 三种数据类型之间的转换 ------------------------------------------------------------- # 如何将因子(factor)类型里的数值转换对应的数值型呢? # 有两种方式 # 首先对year数值型变量转化成因子型(这个只是为了做个示范,如果本身有因子型就不需要再做转换) dat$year <- factor(dat$year) class(dat$year) # 然后再尝试将其转化数值 year <- as.numeric(as.character(dat$year)) class(year) # y1 <- as.numeric(levels(dat$year)[dat$year]) # class(y1) # 因子型转数值型的思路:先转换成字符型然后再转换成数值型。
# 如何将字符型的数值转换对应的数值型? v3_num <- as.data.frame(lapply(dat$value3,as.numeric)) str(v3_num) # 我们查看结果发现是转化了但是变成了1行N列的值 # 需要对其进行转置 # 由于转置之后数据框变成了矩阵,用data.frame把矩阵又变回数据框 # 同时在转数据框的时候一定要加上stringsAsFactors = F v3_t <- t(v3_num) v3_t_num <- data.frame(v3_t, stringsAsFactors = F) dat$v3 <- v3_t_num$v3_t str(dat) # 最后可以看到v3的结果和value4的结果是一样的,说明成功了。
# 如何对字符型和因子型进行互转? # 将字符型转换成因子型 value3 <- as.character(dat$value3) class(value3)
# 将因子型转换成字符型 value3_1 <- factor(value3) class(value3_1)
|