R語言學習3:數據框處理(1)


本系列是一個新的系列,在此系列中,我將和大家共同學習R語言。由於我對R語言的了解也甚少,所以本系列更多以一個學習者的視角來完成。

參考教材:《R語言實戰》第二版(Robert I.Kabacoff),書中所提到的John Cook的優秀博文,關於代碼規范的《來自Google的R語言編碼風格指南》。

Part 1:變量管理

Section 1:創建變量——transform()

為數據框創建新變量,可以使用數據框的$運算符,如果df$variablevariable不屬於原數據框,則會創建一個新的數據框。

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()

變量的重編碼,指的是根據變量的現有值創建新值的過程,如分箱、糾正錯誤值等。

為方便以下內容的示范,使用書中給出的原始數據框:

image-20210219130013035
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(年月日),其他格式化符號如下表。

image-20210219134409881

對於本例,時間格式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()函數。

image-20210219143244148

其中,is.datatype()返回一個TRUEFALSE,可以用於控制流。

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

刪除變量:可以使用如下的語句來刪除q4q5兩個變量。

myvars <- names(leadership) %in% c("q4", "q5")
newdata <- leadership[!myvars]

這里,myvars是一個邏輯變量,除了q4q5T以外其他地方都是F,因此取反,表示除了q4q5F外其他都是T(需要保留)。

另外,如果知道q4q5是第9、第10個變量,可以簡單使用

newdata <- leadership[c(-9, -10)]

進行刪除。

選入觀測:選入觀測也可以使用邏輯變量。現在,選入觀測時間在2009-01-012014-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表達式,且fromto可以不必是數值。

如要隨機抽取觀測,可以使用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中還有許多可選擇的參數,如stringsAsFactorsrow.names等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM