用R語言做數據清理(詳細教程)


數據的清理

如同列夫托爾斯泰所說的那樣:“幸福的家庭都是相似的,不幸的家庭各有各的不幸”,糟糕的惡心的數據各有各的糟糕之處,好的數據集都是相似的。一份好的,干凈而整潔的數據至少包括以下幾個要素:

1、每一個觀測變量構成一列
2、每一個觀測對象構成一行
3、每一個類型的觀測單元構成一個表
就像我們最常接觸的鳶尾花數據:

##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa

每一列就是觀測的指標:花瓣長度,花瓣寬度,萼片長度,萼片寬度,種類;每一行就是一株鳶尾花的觀測值,構成整張表的元素就是四個數值變量,一個分類分類變量。

然而出於排版的考慮我們抓下來的數據往往不是那么的友好,比如說我們可以看到的數據通常是這樣的:

##   religion <10k 10k-50k 50k-100k
## 1 Agnostic   12      31       23
## 2 Buddhist   58      43       43
## 3 Catholic   79      56       23

而不是:

##   religion   income freq
## 1 Agnostic     <10k   12
## 2 Agnostic  10k-50k   58
## 3 Agnostic 50k-100k   79
## 4 Buddhist     <10k   31

當然,除了這種把列表每一列代表一些數值這種情況外,還有多個變量儲存為一列(比如列表不僅以"<10k","10k-50k","50k-100k"做表頭,甚至還加上性別信息"m<10k","m10k-50k","m50k-100k","f<10k","f10k-50k","f50k-100k",其中m代表男性,f代表女性),還有更過分的將列表的變量不僅儲存在列中,行中也有統計變量。

面對這些不好的table,我們首先要做的就是數據管理,將數據整理為一個干凈的數據集。

數據管理

按照en:DAMA的定義:“數據資源管理,致力於發展處理企業數據生命周期的適當的建構、策略、實踐和程序”。這是一個高層而包含廣泛的定義,而並不一定直接涉及數據管理的具體操作(如關系數據庫的技術層次上的管理)。我們這里主要講述對於數據的變量命名與數據的合並,旨在方便數據共享。

數據管理首先要做的就是大致上了解你的數據,比如有什么樣的變量,每一行大致長成什么樣,最常用的就是head(),tail().
我們要做的基本上就是這么幾項工作:

  • 給每一個變量命名,而不是V1,V2,如果有必要可以給出code book。

  • 每個變量名最好具有可讀性,除非過長,否則不要用縮寫,例如AgeAtDiagnosis這個命名遠好於AgeDx。

  • 通常來說,最好將數據放在一張表里面,如果因為數據過多,項目過雜,分成了幾張表。那么一定需要有一列使得這些表之間能夠連接起來,但盡量避免這樣做。

我們以UCI的Human Activity Recognition Using Smartphones Data Set 為例來看看數據是如何變成一個基本符合要求的數據。這個數據我們已經下載下來了,其中關於數據的詳細信息可以參閱read me文檔,由於UCI的數據通常都是一個基本合乎規范的數據集(主要是指它的數據集的變量名都是以V1,V2來命名的)加上一個code book。那么我們看看各個數據的名稱(在feature文件里)

setwd("F:/coursera/Data Science/peer assignment/get clean and tidy data/UCI HAR Dataset")name <- read.table("./features.txt", stringsAsFactors = F) head(name)
##   V1                V2
## 1  1 tBodyAcc-mean()-X
## 2  2 tBodyAcc-mean()-Y
## 3  3 tBodyAcc-mean()-Z
## 4  4  tBodyAcc-std()-X
## 5  5  tBodyAcc-std()-Y
## 6  6  tBodyAcc-std()-Z

我們可以看到各個特征的名稱直接標在數據上是非常不友善的,我們為了讓他具有可讀性,我們以展示在我們眼前的6個數據為例:

variablename <- head(name)# 將標簽中的大寫字母轉為小寫,我們這里沒有所以不再賦值,如果需要全變為大寫,可以使用touppertolower(variablename$V2)
## [1] "tbodyacc-mean()-x" "tbodyacc-mean()-y" "tbodyacc-mean()-z"
## [4] "tbodyacc-std()-x"  "tbodyacc-std()-y"  "tbodyacc-std()-z"
# 將變量名分離成3部分splitNames <- strsplit(variablename$V2, "-")splitNames[[1]]
## [1] "tBodyAcc" "mean()"   "X"
# 將變量名合成有意的名稱named <- function(x) { rr <- paste(x[2], x[1], "-", x[3], sep = "") chartr("()", "of", rr) } sapply(splitNames, named)
## [1] "meanoftBodyAcc-X" "meanoftBodyAcc-Y" "meanoftBodyAcc-Z"
## [4] "stdoftBodyAcc-X"  "stdoftBodyAcc-Y"  "stdoftBodyAcc-Z"

用這樣的名字給數據集命名就感覺舒服多了,我們將一些R中對字符串常用的操作函數總結如下,方便我們對數據名稱的修改:

  • sub:替換字符串中的第一個模式為設定模式(pattern).

  • gsub:全局替換字符串中的相應模式

  • grep,grepl:這兩個函數返回向量水平的匹配結果,grep僅返回匹配項的下標,而grepl返回所有的查詢結果,並用邏輯向量表示有沒有找到匹配。

  • nchar:統計字符串單字數目

  • substr:取子串

  • paste:將字符串鏈接起來,sep參數可以設置連接符

  • str_trim:去掉字符串空格

變量的名稱建議滿足如下要求:

  • 英文變量名盡可能用小寫

  • 盡可能的描述清楚變量特征 (Diagnosis versus Dx)

  • 不要太復雜

  • 不要有下划線、點、空格

字符型變量應該滿足:

  • 是因子類型的應該轉化為factor

  • 因子盡可能具有一定的描述性 (例如:如果0/1表示真假,那么用TRUE/FALSE代替0/1;在表示性別時用Male/Female代替M/F)

接下來我們討論數據集的合並,主要使用函數merge。
我們以下面兩個數據集的合並為例:

df1 <- data.frame(id = sample(1:10), reviewer_id = sample(5:14), time_left = sample(1321:1330), x = rnorm(10))df2 <- data.frame(id = sample(1:10), answer = rep("B", 10), time_left = sample(321:330), y = rnorm(10)) head(df1, n = 3)
##   id reviewer_id time_left       x
## 1  3           9      1326 -0.9232
## 2 10           5      1322  2.5069
## 3  1          14      1330  2.2478
head(df2, n = 3)
##   id answer time_left      y
## 1  1      B       329 0.8180
## 2 10      B       327 1.4639
## 3  9      B       323 0.8141

merge函數調用格式為:

merge(x, y, by = intersect(names(x), names(y)),
      by.x = by, by.y = by, all = FALSE, all.x = all, all.y = all,
      sort = TRUE, suffixes = c(".x",".y"),
      incomparables = NULL, ...)

參數說明:

  • x,y:兩個數據框

  • by, by.x, by.y:指定用於合並的列的名稱。

  • all,all.x,all.y:默認的all = FALSE相當於自然連接, 或者說是內部鏈接. all.x = TRUE是一個左連接, all.y = TRUE是一個又連接, all = TRUE 相當於一個外部鏈接.

仔細觀察下面3個例子你就會發現其中的奧秘:

mergedData <- merge(df1,df2,by.x="reviewer_id",by.y="id",all=TRUE) head(mergedData)
##   reviewer_id id time_left.x      x answer time_left.y       y
## 1           1 NA          NA     NA      B         329  0.8180
## 2           2 NA          NA     NA      B         330 -0.7706
## 3           3 NA          NA     NA      B         325 -0.4851
mergedData <- merge(df1,df2,by.x="id",by.y="id",all=TRUE) head(mergedData)
##   id reviewer_id time_left.x        x answer time_left.y       y
## 1  1          14        1330  2.24783      B         329  0.8180
## 2  2          12        1324  1.03181      B         330 -0.7706
## 3  3           9        1326 -0.92317      B         325 -0.4851
## 4  4           7        1321 -0.07841      B         322  0.1801
mergedData2 <- merge(df1,df2,all=TRUE) head(mergedData2)
##   id time_left reviewer_id       x answer       y
## 1  1       329          NA      NA      B  0.8180
## 2  1      1330          14  2.2478   <NA>      NA
## 3  2       330          NA      NA      B -0.7706

在plyr包中還提供了join,join_all,arrange等函數來實現表的連接,但我想merge這個函數已經足夠用了,所以我們不在多說。當然,在極少數特別好的情況下(比如列的變量是一致的,或者行的觀測個體是一致的時候)rbind,cbind也是有用的。

有些時候我們會遇到一些特殊的字符串:日期。R中提供了各式各樣的函數來處理時間:

Sys.setlocale("LC_TIME", "C")
## [1] "C"
x <- c("1jan1960", "2jan1960", "31mar1960", "30jul1960")z <- as.Date(x, "%d%b%Y") format(z, "%a %b %d")
## [1] "Fri Jan 01" "Sat Jan 02" "Thu Mar 31" "Sat Jul 30"
weekdays(z)
## [1] "Friday"   "Saturday" "Thursday" "Saturday"
julian(z)
## [1] -3653 -3652 -3563 -3442
## attr(,"origin")
## [1] "1970-01-01"
transform(z, weekend = as.POSIXlt(z, format = "%Y/%m/%d")$wday %in% c(0, 6))
##       X_data weekend
## 1 1960-01-01   FALSE
## 2 1960-01-02    TRUE
## 3 1960-03-31   FALSE
## 4 1960-07-30    TRUE

數據操作與整合

說到數據操作,這也是一個十分寬泛的話題,在這里我們就以下4個方面進行介紹:

  • 數據的篩選,過濾:根據一些特定條件選出或者刪除一些觀測

  • 數據的變換:增加或者修改變量

  • 數據的匯總:分組計算數據的和或者均值

  • 數據的排序:改變觀測的排列順序

然而在進行這一切之前首先要做的就是了解你的數據,我們以世界銀行的數據Millennium Development Goals為例,來一步步演示如何進行數據操作:

if (!file.exists("C:/Users/yujun/Documents/MDG_Data.csv")) { download.file("http://databank.worldbank.org/data/download/MDG_csv.zip","F:/MDG.zip") unzip("F:/MDG.zip") }MDstats<-read.csv("C:/Users/yujun/Documents/MDG_Data.csv")

首先先來看一部分數據:

head(MDstats)
##   Country.Name Country.Code
## 1  Afghanistan          AFG
## 2  Afghanistan          AFG
## 3  Afghanistan          AFG
tail(MDstats)
##       Country.Name Country.Code
## 33093     Zimbabwe          ZWE
## 33094     Zimbabwe          ZWE
## 33095     Zimbabwe          ZWE
## 33096     Zimbabwe          ZWE

我們顯然發現了這不是一個tidy data,那么我們先將其變換為我們喜歡的tidy data,之后再看看數據摘要及數據集各單元的屬性:

##   countryname countrycode
## 1 Afghanistan         AFG
## 2 Afghanistan         AFG
## 3 Afghanistan         AFG
## 4 Afghanistan         AFG
## 5 Afghanistan         AFG
## 6 Afghanistan         AFG
##                                                               indicatorname
## 1             Adolescent fertility rate (births per 1,000 women ages 15-19)
## 2                                  Agricultural support estimate (% of GDP)

我們可以看看各個數值數據的分位數:

quantile(MDstatsMelt$value,na.rm=TRUE)
##         0%        25%        50%        75%       100% 
## -9.431e+08  1.054e+01  5.060e+01  9.843e+01  7.526e+13

看看各個國家的統計數據有多少:

table(MDstatsMelt$countrycode)
## 
##  ABW  ADO  AFG  AGO  ALB  ARB  ARE  ARG  ARM  ASM  ATG  AUS  AUT  AZE  BDI 
## 3216 3216 3216 3216 3216 3216 3216 3216 3216 3216 3216 3216 3216 3216 3216 
##  BEL  BEN  BFA  BGD  BGR  BHR  BHS  BIH  BLR  BLZ  BMU  BOL  BRA  BRB  BRN 

看看缺失值:

sum(is.na(MDstatsMelt$value)) #總的缺失值
## [1] 495519
colSums(is.na(MDstatsMelt))  #每一列的缺失值
##   countryname   countrycode indicatorname indicatorcode          year 
##             0             0             0             0             0 
##         value 
##        495519
# 如果我們用回tidy前的數據集,那么這個函數會顯得比較有用colSums(is.na(MDstats))
##   Country.Name   Country.Code Indicator.Name Indicator.Code          X1990 
##              0              0              0              0          23059 
##          X1991          X1992          X1993          X1994          X1995 
##          22293          21672          21753          21491          20970 
##          X1996          X1997          X1998          X1999          X2000 
##          20680          20448          20419          19933          18822 
# 等價的處理方式stat <- function(x) { sum(is.na(x)) } tapply(MDstatsMelt$value, MDstatsMelt$year, stat)
## X1990 X1991 X1992 X1993 X1994 X1995 X1996 X1997 X1998 X1999 X2000 X2001 
## 23059 22293 21672 21753 21491 20970 20680 20448 20419 19933 18822 19598 
## X2002 X2003 X2004 X2005 X2006 X2007 X2008 X2009 X2010 X2011 X2012 X2013 
## 19119 19478 19269 18704 19044 18641 19256 19162 18756 20360 21967 30625

統計某個國家的統計數據占總統計數目的多少

table(MDstatsMelt$countryname %in% c("China"))
## 
##  FALSE   TRUE 
## 791136   3216
prop <- table(MDstatsMelt$countryname %in% c("China"))[2]/sum(table(MDstatsMelt$countryname %in% c("China")))prop
##     TRUE 
## 0.004049

看看數據集的大小:

object.size(MDstatsMelt)
## 22301832 bytes
print(object.size(MDstatsMelt),units="Mb")
## 21.3 Mb

至此,我們可以說我們對數據有了一定的了解。另外值得一提的是,對於某些特定的數據,也許xtabs,ftable是有用的。

數據的篩選

要提取相應內容的數據,最為常用的就是提取相應元素,比如提取某個元素,提取某一行,某一列。我們通過下面下面的例子來學習:

data<-data.frame(a=sample(1:10),b=rep(c("a","b"),each=5),cdf=rnorm(10))data
##     a b     cdf
## 1   1 a  0.5755
## 2  10 a  0.8087
## 3   2 a  0.9810
## 4   7 a -0.4635
## 5   4 a  0.5094
#提取相應元素data[2,1]
## [1] 10
data[[1]][[2]]
## [1] 10
data[[c(1,2)]]
## [1] 10
data$a[2]
## [1] 10
#提取某一列data[[3]]
##  [1]  0.5755  0.8087  0.9810 -0.4635  0.5094  1.0514 -1.5338  1.0047
##  [9]  1.0004 -1.3566
data$cdf
##  [1]  0.5755  0.8087  0.9810 -0.4635  0.5094  1.0514 -1.5338  1.0047
##  [9]  1.0004 -1.3566
data$c
##  [1]  0.5755  0.8087  0.9810 -0.4635  0.5094  1.0514 -1.5338  1.0047
##  [9]  1.0004 -1.3566
data[["c"]]
## NULL
data[["c", exact = FALSE]]
##  [1]  0.5755  0.8087  0.9810 -0.4635  0.5094  1.0514 -1.5338  1.0047
##  [9]  1.0004 -1.3566

數據的篩選還有一個最為常用的的就是移除缺失值:

data<-data.frame(a=c(sample(1:5),NA,NA,sample(6:10)),b=c(rep(c("a","b"),each=5),NA,NA),cdf=rnorm(12))data
##     a    b       cdf
## 1   5    a -0.276400
## 2   1    a -1.861240
good <- complete.cases(data)data[good, ]
##    a b     cdf
## 1  5 a -0.2764
## 2  1 a -1.8612
## 3  3 a -2.0280
bad <- as.data.frame(is.na(data))data[!(bad$a|bad$b|bad$c),]
##    a b     cdf
## 1  5 a -0.2764
## 2  1 a -1.8612

數據篩選有時是為了獲得符合條件的數據:

X <- data.frame("var1"=sample(1:5),"var2"=sample(6:10),"var3"=sample(11:15))X <- X[sample(1:5),]; X$var2[c(1,3)] = NAX
##   var1 var2 var3
## 2    5   NA   13
## 5    3    6   15
## 1    2   NA   12
## 3    1    8   11
## 4    4    9   14
X[(X$var1 <= 3 & X$var3 > 11),]
##   var1 var2 var3
## 5    3    6   15
## 1    2   NA   12
subset(X,(X$var1 <= 3 & X$var3 > 11))
##   var1 var2 var3
## 5    3    6   15
## 1    2   NA   12
X[(X$var1 <= 3 | X$var3 > 15),]
##   var1 var2 var3
## 5    3    6   15
## 1    2   NA   12
## 3    1    8   11
X[which(X$var1 <= 3 | X$var3 > 15),]
##   var1 var2 var3
## 5    3    6   15
## 1    2   NA   12
## 3    1    8   11

對於取子集的函數subset,在幫助文檔中有一段warning是值得我們注意的:“This is a convenience function intended for use interactively. For programming it is better to use the standard subsetting functions like [, and in particular the non-standard evaluation of argument subset can have unanticipated consequences."

數據的變換

常見的數據變換函數有:

  • abs(x) 絕對值

  • sqrt(x) 開根號

  • ceiling(x) 求上線,例:ceiling(3.475) = 4

  • floor(x) 求下線,例:floor(3.475) = 3

  • round(x,digits=n) 四舍五入,例:round(3.475,digits=2) = 3.48

  • signif(x,digits=n) 四舍五入,例:signif(3.475,digits=2) = 3.5

  • cos(x), sin(x) etc.三角變換

  • log(x) 對數變換

  • log2(x), log10(x) 以2、10為底的對數變換

  • exp(x) 指數變換

除此以外,我們還經常對數據加標簽,以期在回歸中測量其效應。我們以MASS包的shuttle數據集為例,想知道不同類型的風(wind)是否需要使用不同的裝載機(use),這里我們希望將head wind標記為1,auto use也記為1,我們可以按照如下辦法設置虛擬變量:

library(MASS)
data(shuttle) head(shuttle)
##   stability error sign wind   magn vis  use
## 1     xstab    LX   pp head  Light  no auto
## 2     xstab    LX   pp head Medium  no auto
## 3     xstab    LX   pp head Strong  no auto
## 4     xstab    LX   pp tail  Light  no auto
## 5     xstab    LX   pp tail Medium  no auto
## 6     xstab    LX   pp tail Strong  no auto
## Make our own variables just for illustrationshuttle$auto <- 1 * (shuttle$use == "auto")shuttle$headwind <- 1 * (shuttle$wind == "head") head(shuttle)
##   stability error sign wind   magn vis  use auto headwind
## 1     xstab    LX   pp head  Light  no auto    1        1
## 2     xstab    LX   pp head Medium  no auto    1        1

當然對於因子類型變量,relevel函數在線性模型的分析中也是能取得等價效果的。

有些時候,我們還常常將連續數據離散化,這時我們需要用到函數cut:

data <- rnorm(1000) table(cut(data, breaks = quantile(data)))
## 
##  (-3.28,-0.637] (-0.637,0.0321]  (0.0321,0.672]    (0.672,3.37] 
##             249             250             250             250
library(Hmisc)
table(cut2(data, g = 4))
## 
## [-3.2847,-0.6372) [-0.6372, 0.0334) [ 0.0334, 0.6829) [ 0.6829, 3.3704] 
##               250               250               250               250
detach("package:Hmisc", unload = TRUE)

獲得分組區間后,我們只需要將區間的因子重命名就成功的實現了數據的離散化。

數據的匯總

對數據進行匯總,分類匯總是我們也比較常用的,比如對行或列求和,求均值,求分位數:

data <- matrix(1:16, 4, 4)data
##      [,1] [,2] [,3] [,4]
## [1,]    1    5    9   13
## [2,]    2    6   10   14
## [3,]    3    7   11   15
## [4,]    4    8   12   16
apply(data, 2, mean)
## [1]  2.5  6.5 10.5 14.5
apply(data, 1, sum)
## [1] 28 32 36 40
apply(data, 1, quantile, probs = c(0.25, 0.75))
##     [,1] [,2] [,3] [,4]
## 25%    4    5    6    7
## 75%   10   11   12   13
apply(data, 2, quantile, probs = c(0.25, 0.75))
##     [,1] [,2]  [,3]  [,4]
## 25% 1.75 5.75  9.75 13.75
## 75% 3.25 7.25 11.25 15.25

有時候,為了更快些,我們會用一些函數替代apply:

  • rowSums = apply(x, 1, sum)

  • rowMeans = apply(x, 1, mean)

  • colSums = apply(x, 2, sum)

  • colMeans = apply(x, 2, mean)

我們有時也會處理一些列表,對列表的分類匯總我們會用到sapply,lapply,不同的是前者返回一個向量或矩陣,后者返回一個列表,例:

x <- list(a = 1:10, beta = exp(-3:3), logic = c(TRUE,FALSE,FALSE,TRUE)) lapply(x, mean)
## $a
## [1] 5.5
## 
## $beta
## [1] 4.535
## 
## $logic
## [1] 0.5
sapply(x, mean)
##     a  beta logic 
## 5.500 4.535 0.500
# median and quartiles for each list elementlapply(x, quantile, probs = 1:3/4)
## $a
##  25%  50%  75% 
## 3.25 5.50 7.75 
## 
## $beta
##    25%    50%    75% 
## 0.2516 1.0000 5.0537 
## 
## $logic
## 25% 50% 75% 
## 0.0 0.5 1.0
sapply(x, quantile)
##          a     beta logic
## 0%    1.00  0.04979   0.0
## 25%   3.25  0.25161   0.0
## 50%   5.50  1.00000   0.5
## 75%   7.75  5.05367   1.0
## 100% 10.00 20.08554   1.0

有時候我們還會進行分類匯總,如統計男女工資均值,這時你可以用tapply:

group <- (rbinom(32, n = 20, prob = 0.4))groups <- factor(rep(1:2,10)) tapply(group, groups, length) 
##  1  2 
## 10 10
tapply(group, groups, sum)
##   1   2 
## 135 122
tapply(group, groups, mean)
##    1    2 
## 13.5 12.2

數據的排序

數據的排序需要用到的函數常見的有sort和order,其中sort返回排序的結果,order返回對應數據的排名。例:

X <- data.frame("var1"=sample(1:5),"var2"=sample(6:10),"var3"=sample(11:15))X <- X[sample(1:5),]X$var2[c(1,3)] <- NAsort(X$var2,decreasing=TRUE)
## [1] 9 8 6
sort(X$var2,decreasing=TRUE,na.last=TRUE)
## [1]  9  8  6 NA NA
order(X$var2,decreasing=TRUE)
## [1] 2 5 4 1 3
order(X$var2,decreasing=TRUE,na.last=TRUE)
## [1] 2 5 4 1 3
X[order(X$var2),]
##   var1 var2 var3
## 2    1    6   13
## 5    5    8   15
## 4    4    9   11
## 1    2   NA   14
## 3    3   NA   12
#deal with the linkX$var2[c(1)] <- sample(na.omit(X$var2),1)X[order(X$var2,X$var3),]
##   var1 var2 var3
## 2    1    6   13
## 5    5    8   15
## 4    4    9   11
## 1    2    9   14
## 3    3   NA   12

有些時候,更為強大的aggregate函數是我們需要的,我們以R的內置數據集state.x77為例:

aggregate(state.x77,          list(Region = state.region, Cold = state.x77[,"Frost"] > 130), mean)
##          Region  Cold Population Income Illiteracy Life Exp Murder HS Grad
## 1     Northeast FALSE     8802.8   4780     1.1800    71.13  5.580   52.06
## 2         South FALSE     4208.1   4012     1.7375    69.71 10.581   44.34
## 3 North Central FALSE     7233.8   4633     0.7833    70.96  8.283   53.37
## 4          West FALSE     4582.6   4550     1.2571    71.70  6.829   60.11
## 5     Northeast  TRUE     1360.5   4308     0.7750    71.44  3.650   56.35
## 6 North Central  TRUE     2372.2   4589     0.6167    72.58  2.267   55.67

當然,這里還有一個更為基本與靈活的函數,split,可以幫助你將數據分為若干張滿足分類條件的表,你可以一張一張的處理它們:

library(datasets)
head(airquality)
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    NA      NA 14.3   56     5   5


免責聲明!

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



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