小技巧--對常用的三種數(shù)據(jù)類型進行轉換(數(shù)值型、字符型和因子型)。為什么要了解數(shù)據(jù)結構之間的差異和做對應轉換呢?通常在畫圖和做分析時,不同情況對數(shù)據(jù)類型需求不一樣,特別是新手在學習代碼的時候,如果不清楚數(shù)據(jù)結構很容易造成錯誤。針對不同情況,根據(jù)自己的需求調整對應的數(shù)據(jù)類型,這樣有助于我們更好地學習和運行code。通常所有的數(shù)據(jù)我們統(tǒng)稱為向量,針對不同數(shù)據(jù)集結構(這里可以參考我們以前發(fā)表的推文:【R分享|實戰(zhàn)】 新手福利~認識數(shù)據(jù)集的內在),主要可分為兩類向量。一是,原子向量;二是,遞歸向量。我們可以借助下面這張圖(黃師兄的總結)來理解:也就是說,原子向量主要包括:logical,integer, double, character等類型,其中integer和double統(tǒng)稱為numeric(數(shù)值型向量)。而列表通常被稱為遞歸向量,因為它可以包含其他列表。  針對這部分內容,以代碼的形式給大家分享和講解,希望能幫助大家少走彎路。首先,我們先構造數(shù)據(jù)集,并解讀數(shù)據(jù)集中不同的數(shù)據(jù)類型:# 不同數(shù)據(jù)類型之間的差異與轉換 -------------------------- # 隨機構造數(shù)據(jù)集 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) # 打包數(shù)據(jù)集 dat <- data.frame(treatment, type, year, value1, value2, value3, value4) # 查看數(shù)據(jù)結構 str(dat) # 從查詢的結果來看,treatment這個變量是字符型-“cha”向量; # type為因子型向量(factor)w/4表示有4個因子 # year是整數(shù)-“int”數(shù)值型向量;value1與year是同樣類型的數(shù)值; # value2是數(shù)值型向量;value3是字符型;value4是與v3相同值的數(shù)值型變量。
上述code的結果:
 然后,我們分別以繪圖和跑模型的方式對其差異進行講解:# 以畫圖為例進行不同數(shù)據(jù)類型變量的講解: library(ggplot2) ggplot(data = dat, aes(x = year, y = value1, color=treatment))+ geom_point()+ geom_line()+ labs(x="year") # 從圖來看,由于year是數(shù)值型變量,畫圖時候會默認成連續(xù)型的所以會有間隔
# 這里我們將year改成因子型變量再對其進行展示: ggplot(dat, aes(as.factor(year), value1, color=treatment))+ geom_point()+ # geom_line()+ geom_path(group=treatment)+ labs(x="year") # 由于對x的變量進行了因子型轉換,這個地方也是大家比較容易出錯的。 # 對變量進行因子轉化后,geom_line函數(shù)不能識別分組; # 因此利用geom_path函數(shù)的分組進行繪制。


從兩張圖來看,結果似乎差異不大,僅僅在x軸的label上出現(xiàn)了差異。圖1為數(shù)值型的x軸是連續(xù)的,默認為數(shù)值,并不是實際的年份,所以會出現(xiàn)0.5這樣的年份表達。 如果,我們將y軸用字符型的數(shù)據(jù)進行繪圖,會有怎么的差異:
# 如果我們使用字符型作為我們的x軸和y軸,看看結果如何; ggplot(dat, aes(treatment, value3, fill = type))+ geom_bar(stat = "identity", position = "dodge")
# 用相同的數(shù)值,但是不同的數(shù)據(jù)類型y,比較兩者差異 ggplot(dat, aes(treatment, value4, fill = type))+ geom_bar(stat = "identity", position = "dodge")


從兩個結果來看,存在明顯差異。如果是數(shù)值型向量,柱狀圖會默認展示一個總的柱狀圖;而如果是字符型向量,可以把每一個值都看作是個體,展示所有的情況。 接下來,我們從模型方面來理解,這里以最簡單的線性模型為例:# 如果自變量為數(shù)值型 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)
當自變量為數(shù)值型時: 

當自變量為字符型時:

從這里可以看出當自變量為因子型或者字符型時,會將每個年份都作為一個個體與因變量做擬;而數(shù)值型是一個總體。并且,需要考慮當用其他更加復雜的模型,如果是字符型或因子型會延長模型的計算時間。特別是混合效應模型。 最后,我們可以根據(jù)自己的需要對三種數(shù)據(jù)類型之間進行轉換:# 三種數(shù)據(jù)類型之間的轉換 ------------------------------------------------------------- # 如何將因子(factor)類型里的數(shù)值轉換對應的數(shù)值型呢? # 有兩種方式 # 首先對year數(shù)值型變量轉化成因子型(這個只是為了做個示范,如果本身有因子型就不需要再做轉換) dat$year <- factor(dat$year) class(dat$year) # 然后再嘗試將其轉化數(shù)值 year <- as.numeric(as.character(dat$year)) class(year) # y1 <- as.numeric(levels(dat$year)[dat$year]) # class(y1) # 因子型轉數(shù)值型的思路:先轉換成字符型然后再轉換成數(shù)值型。
# 如何將字符型的數(shù)值轉換對應的數(shù)值型? v3_num <- as.data.frame(lapply(dat$value3,as.numeric)) str(v3_num) # 我們查看結果發(fā)現(xiàn)是轉化了但是變成了1行N列的值 # 需要對其進行轉置 # 由于轉置之后數(shù)據(jù)框變成了矩陣,用data.frame把矩陣又變回數(shù)據(jù)框 # 同時在轉數(shù)據(jù)框的時候一定要加上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)
|