R數據處理基礎篇(一)

2021-02-20 表哥有話講

先用幾個問題檢驗一下你是否需要看這篇文章

在使用R做數據分析的一個完整的過程包括數據的獲取,數據的前期處理,之後才是使用「整齊」的數據來套用模型得出結論。本專題旨在系統地講述使用R語言完成前期的數據處理,英文叫tidy data,將「髒」數據洗乾淨。比如處理掉一些會影響結果準確度的數據,提取出我們想要的內容,或將整個數據集或多個數據集融合、改變成我們想要的形式。這個過程往往是數據處理上最繁榮瑣碎的過程,可能在這裡耗費的時間要過多真正 fit model 所需要的時間。

除了通用的處理之外,本專題還會專門針對缺失值處理、時間處理、讀寫數據等方面,單獨進行介紹。

在數據處理上,R語言本身自帶這一些操作方法,但是有三個主要的缺陷

用法不夠簡潔易記

在處理大量數據時,速度太慢

完成有些需求過於麻煩,或者無法達成。

但是這是R的開源好處就體現出來了,用戶開發了幾個高效處理數據的R包,它們不僅提高了運行速度,而且代碼簡明易記,如果熟練掌握,可以成為處理數據的一大利器。

主要的大數據處理包可以分為兩個派別

本專題講述時,將前者和R自帶基礎函數一起講述,data.table包會單獨開出一個部分來講。

本文使用R語言進行數據處理,不僅包括R自帶的函數,而且包括其他高效處理數據的R包。這個部分共兩篇文章,使用基礎函數和Hadley寫的一系列數據處理包,來完成整個數據處理的基本需求。

本文目錄如下

數據框建立

提取

根據坐標和行列名提取單個數值

提取整行或整列

根據邏輯值判斷提取

提取的衍生物(為什麼這麼說會在後面介紹)

增添


載入R包

本文只需要使用dplyr包

library(dplyr) # 高速處理數據,取代R自帶的一些函數,代碼簡單易記

數據框建立

# 數據框建立
name1 <- c("Bob","Mary","Jane","Kim")
name2 <- c("Bob","Mary","Kim","Jane")
weight <- c(60,65,45,55)
height <- c(170,165,140,135)
birth <- c("1990-1","1980-2","1995-5","1996-4")
accept <- c("no","ok","ok","no")

df1 <- data.frame(name1,weight,height)
rownames(df1) <- letters[1:4] # 賦予行名
df2 <- data.frame(name2,birth,accept)

上面是通過建立向量再組合來創建數據框,日常使用中還有兩種常見獲得數據框的方法


提取

提取看起來簡單,但是方法卻多而雜亂,在這裡我將做一個總結

從大方向上來看是分為三個角度

根據坐標位置來提取

根據行名列名來提取

使用邏輯值判斷提取

一二兩种放在一起說,都是使用[ ]實現提取,[ ]中的內容分為以下5種

[ ]中放兩個維度的坐標、或者行名和列名,提取單個點或多個點

[ ]中放一個兩列的矩陣,可以把每行看成一個坐標x y,用於提取多個點,點的個數和矩陣的行數相等

兩個維度中只指定一個維度(兩個參數中有一個是空著的,即逗號一邊什麼都不加),提取行或列

只有一位維度,即[ ]中只有一個數或者列名,提取列(提取列比行多這種方法)

使用$指定列名提取列(這也是提取列多出來的方法)

下面有這幾種提取方法的實例,看完實例,我會拓展一些更深層次的數據結構。

# 通過[]選擇坐標,確定點
df1[2,3]
# 使用向量確定多個點
df1[c(2,4),c(1,3)]

# 通過[]選擇行列名
df1["a","weight"]
df1["a",2] # 混搭

# 通過矩陣提取多個點,一列指定行,一列指定列
df1[cbind(c(1,2,1),3:1)]
df1[cbind(c("a","b"), c("weight","height"))]

# 通過[]少選擇一個維度,整行整列地選擇(這是比選擇行多的一種方法)
df1[2,] # 取行
df1[,3] # 取列
df1[c(2,3),] # 取多行
df1[,c(2,3)] # 取多列
df1["a",]
df1[,"weight"]

df1[3] # 只接一個數字,選擇列
df1[c(2,3)] # 使用向量則選擇多列

df1$weight # 通過$選擇列名名字來選擇列
# 列名放在[]中選取列
df1["weight"]
df1[c("weight","height")] # 使用向量選擇多列

select(df2,accept)  # dplyr包中函數,等價於 df2$accept

在選擇行和列上有必要進一步說明,關於取出來的仍是數據框還是向量的問題

這是提取數據是否同時進行降維的問題。即使是只有一列的數據框,它仍是二維的,只有變成向量才算是一維的。上面涉及到的多種提取行列的方法,默認得到的結果是數據框還是向量是不一樣的,但是二者之間是有辦法相互轉化的。

# 取行和取列默認不一樣
class(df1[,3]) # "numeric"
class(df1[2,]) # "data.frame"
# 另外三種
class(df1[3]) # "data.frame"
class(df1["weight"]) # "data.frame"
class(df1$weight) # "numeric"

上面輸出的兩種結果中

對於取兩個坐標[ ]的方法來說,drop參數可以調整輸出結果

# drop=T是降維的意思
class(df1[,3,drop=F]) # "data.frame"
class(df1[2,,drop=T]) # "list"
# 取行用drop也不能轉化為向量,那就用unlist
class(unlist(df1[2,])) # "numeric"

對於只接受一個維度參數的方法來說[[ ]]相當於$,可以實現降維

class(df1[["weight"]]) # "numeric"
class(df1[[2]]) # "numeric"

# 注意:[[]]不能作用到選取多列的情況上,因為多列談不上降維
df1[[c("weight","height")]] # 報錯
df1[[1:3]] # 報錯

其他方面
1.關於[[ ]]和$等關於降維方面的使用,讀者可以自行在list和matrix上試。使用下面一條命令查看幫助文檔

help(`[`)

2.模糊匹配

df1$wei

df1$weig <- 1:4
df1$wei

是否支持模糊匹配也可以用參數exact調整

df1[["hei"]] # 默認不支持模糊匹配
df1[["hei",exact=F]] # 支持

df1["hei"]; df1["hei",exact=F] # 單個[]加了也不支持

模糊匹配在函數參數使用上也有體現

seq(1,10,length.out=10)
seq(1,10,len=10)

3.如果指定的數字不是整數,會自動向下取整

(i <- 3.999999999) # 返回4,因為當前保留的位數不夠
# 如果想要改變保留位數,可以用options(digits = 10)修改
# 不過內存中存儲的還是3.999999999
(1:5)[i]  # 3

通過邏輯值判斷選取


df2[df2$accept=="no"|name2=="Bob",]
subset(df2,accept=="no")
filter(df2,accept=="no"|name2=="Bob")

上面這種通過判斷來選取的方式,有一個背後的原理,我們拿[]來說,這是通過邏輯值向量進行的選取

df2$accept=="no"|name2=="Bob"




df2[df2$accept=="no"|name2=="Bob",]

df2[c(T,F,F,T),]

知道了這個原理之後,我們就可以更加靈活地提取數據,因為[ ]中放置的不一定必須是本數據框中的變量,只要是等長邏輯值向量就可以了(注意最後的逗號不要忘記寫就好)

df2[df1$weight>50,]


提取衍生物

我們使用過程中可能涉及到的,修改數據框,按照行或列進行排序,刪除某行某列,插入某行某列。這些如果都單獨來學,會感覺命令非常多、非常亂,但如果看成是提取的衍生物,則不需要花多少精力就能掌握。因為這些其實都是使用了提取的方法,只是各自加入了自己的原理,就包裝成了另外一種東西。我們一項一項來看:

修改

這裡修改數據框其實只是把需要修改的地方用提取的方法提取出來,再賦個值,就實現了對原數據框的更改,基本上沒有什麼新東西。

df1[2,3] <- 160;df1
df2$accept[df2$accept=="ok"] <- "yes"
df2 # 數據框發生了改變

我們會發現,這裡每次使用數據框中的一列時,都要使用$,非常麻煩,可以使用within函數避免這樣的麻煩

df2 <- data.frame(name2,birth,accept,stringsAsFactors=F)
within(df2,{accept[accept=="ok"]<-"yes"
     name2[name2=="Bob"]<-"BOB"})

當其他時候使用數據框中的列進行計算時,如果不想用$,可以使用attach函數

df2 <- data.frame(name2,birth,accept,stringsAsFactors=F)
attach(df2)
2*weight
detach(df2)

用這種方法一定要注意最後detach,否則會搞亂命名空間,由於容易忘記,一般不推薦這種方法,我們還可以使用with函數

with(df2,{a <- weight*2
         a^3})

刪除

不想要哪行,就在哪行用負數,其實相當於提取了其他行,組成了一個新的數據框。根據這個原理,使用邏輯值向量也可以實現刪除行列。

df1[-c(2,3),]
df1[,c(T,F,T)]

排序

R語言使用基礎函數處理向量、數據框等,都不能直接對其本身修改,無論是改變一個值,還是排序,刪除某一列,得到的都不再是原來的數據框了。所以排序其實就是一個按順序提取的過程。

R中自帶的方法是使用order函數,生成大小順序的索引

df1_order_row <- df1[order(df1$weight),]
# 我們可以拆分來看
order(df1$weight) # 3 4 1 2
# 上面的結果意味著第三個是最小的,最先被提取出來,放在第一行,接下來是第4個第二小……

# 先按體重,再按身高排序(當體重一樣時)
df1_order_row <- df1[order(c(df1$weight,df1$height)),]

# 按照列名對列排序也是一樣
df1_order_col <- df1[,order(colnames(df1))]

# 使用dplyr包對行更方便、高效地處理
arrange(df1,weight,height)

插入

由於上面說到的特性,R語言沒有辦法在原有向量或數據框中插入內容,唯一的方法就是按照要插入的位置,將數據框分開,即提取出dfa和dfb,再用二者和要加入的內容拼接。這種方法非常繁瑣,尤其是當要在很多地方插入的情況下,本人目前沒有找到更好的方法,如果讀者有好的方法可以在評論區留言。

下一節,我們會介紹以下內容

數據框合併

計算並增加行列

匯總計算

分組計算

融合重鑄

融合重鑄的應用

拆分合併列


參考資料

1.想要快速入門dplyr包,可以看網上的教程,都大同小異,很多都是轉載的同一篇,這裡隨便貼一個 http://blog.163.com/zzz216@yeah/blog/static/16255468420147179438149/

2.一般看完上面的這種教程,就能處理大部分問題了,如果想更系統地了解這個包(dplyr),可以看一看官方幫助文檔。說實話,有很多特別好的功能都不為人所知。

專欄信息

專欄主頁:Data Analysis https://zhuanlan.zhihu.com/Data-AnalysisR專欄目錄:目錄  https://zhuanlan.zhihu.com/p/25780082

文末彩蛋

這次講管道操作,一種數據處理中非常便捷的使用方法,主要基於 magrittr 包,裡面有如下幾個函數

%>%  %T>%  %$%  %<>%

最常用的是第一個 %>% ,如果你載入Hadley的包,就自動可以使用這個函數,不用另外加載magrittr包,如果想了解其他函數再載入這個包,查看文檔來學習,或者看這裡連結 http://blog.fens.me/r-magrittr/

管道操作除了這個包,還有 pipeR 包,這是另外一個系統,有興趣的可以去學一下,這裡簡要介紹一下 %>% 函數

library(dplyr)
name2 <- c("Bob","Mary","Kim","Jane")
weight <- c(60,65,45,55)
height <- c(170,165,140,135)
accept <- c("no","ok","ok","no")
df <- data.frame(name2,weight,height,accept)
# 下面兩個操作等價
select(df,weight:accept)
df %>% select(weight:accept)

所以 %>% 的作用在於把前面的內容放到後面函數中,作為第一個參數。使用這個符號的好處有

我們可以對比一下操作

df
 unlist()

plot(colMeans(matrix(unlist(2*select(df,starts_with("w"))),
      nrow=2)))

w <- select(df,starts_with("w"))
v <- unlist(w*2)
m <- matrix(v,nrow=2)
plot(colMeans(m))

以上三塊內容實現的是相同的目的,我們通過管道函數從前往後讀一下

拿到數據集,先提取首字母是w的列,乘2,轉化為向量,使用這個向量創建一個2行的矩陣,對矩陣每一列求均值,最後畫個圖

我們在再去看一下第二種,括號一層套一層,是不是可讀性差了很多?而且之後如果想加操作還要再往外套

第三種則可讀性提高了一些(但是還是沒有從前往後讀順暢),但是中間加了很多沒有必要的變量,代碼就會很冗餘。

以上是最基本也是最常用的方法,下面展示一些其他用法,更深入的可以去看包的幫助文檔


df$weight %>% {c(min(.), mean(.), max(.))} %>% floor

2 %>% head(df,.)

a <- df %>% .$name2 %>% grep("a",.)

Dwzb , R語言中文社區專欄作者,廈門大學統計專業學生。
知乎專欄:Data Analysis
https://zhuanlan.zhihu.com/Data-AnalysisR 


回復 R              R語言快速入門免費視頻 
回復 統計          統計方法及其在R中的實現
回復 用戶畫像   民生銀行客戶畫像搭建與應用 
回復 大數據      大數據系列免費視頻教程
回復 可視化      利用R語言做數據可視化
回復 數據挖掘   數據挖掘算法原理解釋與應用
回復 機器學習   R&Python機器學習入門 

相關焦點

  • R 數據處理(四)
    R 數據處理(四)前言前面講過了 R 自帶的讀取矩陣型數據的方法,如 read.csv,read.table 等。下面我要介紹的是 tidyverse 中的 readr 包提供的讀取矩陣型數據的方式readr 的目標是提供一種快速友好的方式來讀取矩陣型數據,如 csv, tsv 和 fwf 等。使用1.
  • R數據處理|data.table篇(一)
    data.table包是一個超高性能處理包,在數據處理上代碼異常簡潔,速度非常快。由於data.table的語法主要基於[],有些用法和基礎函數會不一致,所以沒有放在前面兩個專題中一起講,而是單獨拿出來講。在這個系列裡,我會詳細說明data.table和基礎函的差異,並系統地講解data.table包的用法。
  • R數據處理|data.table篇(三)
    本文為data.table包介紹最後一篇,前兩篇連結如下R數據處理|data.table篇(一) - 知乎專欄R數據處理|data.table篇(二) - 知乎專欄本文主要講解data.table包中一些比較不常用的函數,還有data.table包高效的深層原理。
  • 數據分析從零開始實戰 | 基礎篇(三)
    零、寫在前面前面兩篇文章基礎篇(一)和基礎篇(二)講了數據分析虛擬環境創建和pandas讀寫csv、tsv、json格式的數據,今天我們繼續探索pandas讀取數據。本系列學習筆記參考書籍:《數據分析實戰》託馬茲·卓巴斯一、基本知識概要1.利用pandas讀寫Excel文件2.利用pandas讀寫XML文件二、開始動手動腦1.利用Python讀寫Excel讀取,利用Pandas庫的ExcelFile()方法。
  • R 數據處理(六)
    R 數據處理(六)解析文件講到這裡,你應該已經很清楚怎麼解析單個向量了。那麼讓我們回到上節引出的 readr 是如何解析文件的問題。在本節中,將介紹另外兩個新的問題1.策略readr 使用啟發式方法計算出每一列的類型:它讀取前 1000 行,並使用一些(適度保守的)啟發式方法來找出每一列的類型。
  • R 數據處理(十九)—— purrr
    R 數據處理(十九)5. map 函數遍歷向量,並對向量中每個元素執行函數操作,最後返回結果的模式是非常普遍的。假設您希望將線性模型擬合到數據集中的每個組,下面的示例將 mtcars 數據集分割為三個部分(每個圓柱體的值一個),並對每個部分擬合相同的線性模型models <- mtcars %>%   split(.
  • R|數據處理|list的轉化與轉置
    data.frame(l) # 結果同上# 複雜一點# 一個更複雜的list,兩層list,代表不同組別,需要分別轉化為數據框,然後拼接在一起ll <- list(a = list(x = 1:10, y = 2:11, group = 1),           b = list(x = 11:20, y = 12:21, group = 2))# 一法dfll <- do.call
  • 數據科學養成記 之 R語言基礎(2)——關於R包
    在上一節的學習中,我們已經學習了如何將數據導入R中進行數據分析。R作為一種主力的分析語言有著其獨特的優勢:大量的R包可供大家使用,提供方便快捷的數據分析,挖掘。目前有上千個R包(R package)可供大家使用,可從cran-r 下載。
  • 機器學習與數據分析常用術語-基礎篇(一)
    本篇文章將著重介紹機器學習與數據挖掘領域常用的專業術語,希望能在機器學習路上的你帶來幫助,假如你正準備學機器學習或數據挖掘建議你先了解該篇文章後在去學習。一.基礎1.數據集(DataSet)數據集,又稱為資料集、數據集合或資料集合,是一種由數據所組成的集合。程式設計師可以簡單的理解成資料庫表。
  • 數據處理基礎2
    Python 數據處理基礎:Part 2source: https://realpython.com/
  • R語言數據處理全流程教學
    R 語言作為一款功能強大的統計分析、繪圖和數據挖掘軟體,被社會科學領域的研究者們廣泛應用於數據處理和圖表製作等工作。由於 R 語言需要一定的編程基礎,其開源屬性又帶來了千千萬萬的功能包(package),使得 R 語言的初學者常常不知從何入手,不知道學習哪些代碼與功能包足夠滿足自己的統計需求。
  • R語言-stringr-字符串處理
    R包stringr處理字符相對簡單,尤其是我常用Power BI,但是對M語言不熟悉,不會處理字符數據,往往我就先利用R清洗字符數據列。本文記錄工作中常用的字符處理函數,部分案例照搬R for Data Science的字符部分。
  • EBSD晶體學織構基礎及數據處理
    在工程中r值來表示,其值越大,深衝性越好。從圖上可以看出,板材的織構是影響r值的主要因素。板材的γ-纖維織構(<111>||ND,ND為軋面法線方向)越強,其深衝性能越好。板材中的織構與r值有密切關係。
  • R語言-data.table-數據處理
    data.table 包數據處理data.table 包數據處理前言基礎介紹基本格式i j by 使用讀取數據行篩選列篩選總結
  • R語言如何檢測和處理數據缺失值?
    面對一份數據,我們會做數據的缺失值檢測和分析,根據數據的缺失程度,以知道數據的完整性和可用性。實際的數據,絕大部分會有缺失值現象。缺失值的產生與諸多因素有關聯,例如:數據採集不成功,數據採集成功了但是數據確實沒有值,數據的值受其它因素控制等。面對有缺失值的數據,我們要怎麼處理、分析和應用,是我們數據工作者要思考和實踐的命題。
  • 玩轉數據處理120題|Pandas&R
    和我一起玩Python本文精心挑選在數據處理中常見的120種操作並整理成習題發布。
  • 對照著Excel入門R語言表格數據處理
    ")dir()#讀入範例數據,為了方便展示數據僅15行;dt <- read.table("Excel小技巧範例數據1.txt",header=T,sep="\t")dt這一部分對應Excel「開始」選項卡下的排序功能
  • 【Python基礎】如何用Pandas處理文本數據?
    >文本數據是指不能參與算術運算的任何字符,也稱為字符型數據。文本數據具有數據維度高、數據量大且語義複雜等特點,是一種較為複雜的數據類型。今天,我們就來一起看看如何使用Pandas對文本數據進行數據處理。本文目錄    1. string類型的性質        1.1. string與object的區別        1.2. string類型的轉換    2.
  • R語言從入門到精通:Day6-R語言數據操作進階及控制結構
    數據處理是R語言和數據挖掘的重要基礎,要求大家務必熟練操作,所以今天我們就從一個簡單的實例出發,給大家繼續講解數據處理進階及控制結構。1、本節內容重點內容較多,      務必緊跟紅色標記。2、測試數據及代碼      見文末客服小姐姐二維碼。
  • 科研神器Python之數據處理篇
    因此Python很適合材料、化學等領域的科研人員學習來簡化科研中遇到的大量數據處理等任務。結合自身在BMG課題組科研過程中遇到的大量需要機械式處理的重複數據以及學習Python的歷程,在這篇科普文中,我給大家介紹一下我在用Python在處理這類數據時的常用套路。1.