本系列是一個新的系列,在此系列中,我將和大家共同學習R語言。由於我對R語言的了解也甚少,所以本系列更多以一個學習者的視角來完成。
參考教材:《R語言實戰》第二版(Robert I.Kabacoff),書中所提到的John Cook的優秀博文,關於代碼規范的《來自Google的R語言編碼風格指南》。
Part 1:變量管理
Section 1:創建變量——transform()
為數據框創建新變量,可以使用數據框的$運算符,如果df$variable中variable不屬於原數據框,則會創建一個新的數據框。
mydata <- data.frame(
x1 = c(2, 2, 6, 4),
x2 = c(3, 4, 2, 8)
)
mydata$sumx <- mydata$x1 + mydata$x2
mydata$meanx <- mydata$sumx / 2
使用transform()函數,能更方便地創建新變量,其用法是:
mydata <- data.frame(
x1 = c(2, 2, 6, 4),
x2 = c(3, 4, 2, 8)
)
mydata <- transform(mydata,
sumx = x1 + x2,
meanx = (x1 + x2)/2)
除此外,transform()函數也能方便地對數據框執行修改,生成一個修改后的映像。
Section 2:變量的重編碼——within()
變量的重編碼,指的是根據變量的現有值創建新值的過程,如分箱、糾正錯誤值等。
為方便以下內容的示范,使用書中給出的原始數據框:
manager <- c(1, 2, 3, 4, 5)
date <- c("10/24/14", "10/28/14", "10/01/14", "10/12/14", "05/01/14")
country <- c("US", "US", "UK", "UK", "UK")
gender <- c("M", "F", "F", "M", "F")
age <- c(32, 45, 25, 39, 99)
q1 <- c(5, 3, 3, 3, 2)
q2 <- c(4, 5, 5, 3, 2)
q3 <- c(5, 2, 5, 4, 1)
q4 <- c(5, 5, 5, NA, 2)
q5 <- c(5, 5, 2, NA, 1)
leadership <- data.frame(manager, date, country, gender, age,
q1, q2, q3, q4, q5, stringsAsFactors = F)
條件賦值語句可以在條件為TRUE時,為向量的相應位置執行賦值,其用法為
variable[condition] <- expression # 這里condition是一個條件向量
結合within()函數,可以方便地為數據框執行重編碼,within()函數的語法與with()類似,但with()只允許方便地調用數據框中的變量,而within()還允許修改數據框。如,為leadership數據框中的agecat執行重編碼:
leadership$age[leadership$age == 99] <- NA # 將異常值編碼為NA
leadership <- within(leadership,{
agecat <- NA
agecat[age > 75] <- "Elder"
agecat[age <= 75 & age >= 55] <- "Middle Aged"
agecat[age < 55] <- "Young"
})
Section 3:變量重命名——names()
對變量名稱不滿意,可以使用fix(df)函數,交互式地更改變量名稱,也可以使用names()函數。如
names(leadership)[2] <- "testDate"
names(leadership)[6:10] <- c("item1", "item2", "item3", "item4", "item5")
或使用plyr包中的rename函數修改變量名。
leadership <- rename(leadership, c(manager="managerID"))
Part 2:值處理
Section 1:缺失值
缺失值以符號NA表示,意為Not Available,它是不可比較的(即使是x == NA也不行,只能用is.na(x))。在R語言中,缺失值與Inf(正無窮)、-Inf(負無窮)、NaN(不是一個數,Not a Number)不同,以上是它們的符號。
需要注意,含有缺失值的算術表達式和函數的計算結果也是缺失值。多值函數一般擁有na.rm參數,如果想要在計算時免除缺失值的影響,需要指定na.rm=T。
> x <- c(1, 2, NA, 3)
> sum(x)
[1] NA
> sum(x, na.rm=T)
[1] 6
對於數據框,如果缺失值只集中於一小部分觀測,可以使用行刪除手段,具體地,可以使用na.omit()函數,對所有含缺失值的觀測進行刪除。
newdata <- na.omit(leadership) # 函數生成的是一個映像,不會對原數據框產生影響
newdata
Section 2:日期值——as.Date()
要獲得當前的日期,可以使用Sys.Date()函數;要獲得當前的日期與時間,可以使用date()函數。
> date()
[1] "Fri Feb 19 13:56:35 2021"
> Sys.Date()
[1] "2021-02-19"
在R語言中,日期值常常是以字符串的形式輸入的,然后需要使用as.Date()函數轉化成數值形式存儲的日期,其語法為
as.Date(x, "input_format")
這里,input_format是用於讀入日期的適當格式,默認為yyyy-mm-dd(年月日),其他格式化符號如下表。
對於本例,時間格式mm/dd/yy,所以應當使用如下的修改編碼:
myformat <- "%m/%d/%y" # 編碼以字符串形式存儲
leadership$date <- as.Date(leadership$date, myformat)
要改變日期的格式以輸出,可以使用format()函數,其使用格式是
format(x, format="output_format")
---
> m <- Sys.Date()
> format(m, format="%Y/%m/%d")
[1] "2021/02/19"
計算日期之間的差值,可以使用difftime()函數,其使用格式是
difftime(date1, date2, units)
這里units是時間單位,可以使用"auto", "secs", "mins", "days", "weeks"等。
with(leadership, {
difftime(date[2], date[1], units = "days")
})
Time difference of 4 days
最后,要將日期轉化為字符串,使用as.character()函數。
Section 3:類型轉換
要判斷某個值是否是某個類型,使用is.datatype()函數;將數值轉換為某個類型,使用as.datatype()函數。
其中,is.datatype()返回一個TRUE或FALSE,可以用於控制流。
Part 3:數據框處理
Section 1:排序
使用order()函數可以對向量進行排序,order()會對向量重新編碼,接受若干個等長向量分別作為排序的有序關鍵字。
> x <- c("a", "e", "d", "d", "c", "b")
> y <- c(6, 5, 4, 3, 2, 1)
> order(x)
[1] 1 6 5 3 4 2
> order(x, y) # y作為第二排序標准
[1] 1 6 5 4 3 2
對數據框,也可以使用order()函數作為條件排序,其原理是數據框可以按照一個有序向量進行排序。
with(leadership, {
newdata2 <<- leadership[order(gender, -age), 1:5]
})
> newdata2
managerID date country gender age
2 2 2014-10-28 US F 45
3 3 2014-10-01 UK F 25
5 5 2014-05-01 UK F NA
4 4 2014-10-12 UK M 39
1 1 2014-10-24 US M 32
注意,如果想要呈現完整的數據框,[contidion, ]中逗號是不能省略的。
Section 2:數據框合並
橫向合並:即實現兩個數據框的內連接,通過一個或多個共有變量,可以使用merge()函數,其用法為
total <- merge(dataframeA, dataframeB, by="ID") # by指定共有字段
如果不需要考慮外鍵,只是簡單地橫向合並,可以使用cbind()函數,這要求每個對象擁有相同的行數,以相同的順序排序。
縱向合並:即向數據框中增加觀測值,可以使用rbind()函數,這要求兩個數據框擁有相同的變量個數(對順序沒有要求)。
total <- rbind(dataframeA, dataframeB)
如果兩個數據框中變量不同,需要進行預處理:要么刪除dataframeA中的多余變量,要么在dataframeB中創建追加的變量,並將其值設為NA。
Section 3:數據框取子集
選入變量:使用dataframe[, colindex]即可,這里colindex是變量的索引。事實上,如果需要保留全部觀測值,可以直接使用dataframe[colindex]而並不需要逗號。另外,列索引也可以用變量名,如
myvars <- c("q1", "q2", "q3", "q4", "q5")
newdata <- leadership[myvars]
> newdata
q1 q2 q3 q4 q5
1 5 4 5 5 5
2 3 5 2 5 5
3 3 5 5 5 2
4 3 3 4 NA NA
5 2 2 1 2 1
刪除變量:可以使用如下的語句來刪除q4,q5兩個變量。
myvars <- names(leadership) %in% c("q4", "q5")
newdata <- leadership[!myvars]
這里,myvars是一個邏輯變量,除了q4和q5是T以外其他地方都是F,因此取反,表示除了q4和q5是F外其他都是T(需要保留)。
另外,如果知道q4和q5是第9、第10個變量,可以簡單使用
newdata <- leadership[c(-9, -10)]
進行刪除。
選入觀測:選入觀測也可以使用邏輯變量。現在,選入觀測時間在2009-01-01到2014-10-20之間的觀測值,這里which。
startdate <- as.Date("2009-01-01")
enddate <- as.Date("2014-10-20")
newdata <- leadership[leadership$date >= startdate & leadership$date <= enddate, ] # 逗號必須保留
選擇數據框的子集,最簡單的方法是使用subset()函數,它可以一次性完成以上的功能,其使用格式如下:
subset(x, subset, select)
這里,x是要傳入的數據框,subset是要保留觀測的邏輯向量,select是要保留變量的向量。
newdata <- subset(
leadership, gender == "M" & age > 25,
select = gender:q4
)
> newdata
gender age q1 q2 q3 q4
1 M 32 5 4 5 5
4 M 39 3 3 4 NA
可以看到,保留變量的向量可以直接用from:to表達式,且from和to可以不必是數值。
如要隨機抽取觀測,可以使用sample()函數,其用法是
sample(x, size, replace=FALSE)
這里,x表示抽樣元素組成的向量,size表示要抽取的元素數量,replace表示是否是有放回抽樣。要是從數據集中抽樣,可以如此使用:
newsample <- leadership[sample(1:nrow(leadership), 3, replace=F), ]
Section 4:使用SQL查詢
如果是較大的數據集,可以使用SQL語句進行查找,這依賴於sqldf庫中的sqldf函數。
library(sqldf)
attach(mtcars)
search <- "SELECT * FROM mtcars WHERE carb=1 ORDER BY mpg"
newdf <- sqldf(search, row.names=T)
sqldf中還有許多可選擇的參數,如stringsAsFactors、row.names等。
