R语言数据集常用操作汇总

在做数据挖掘时,拿来的数据集一般不能直接用,要进行一些操作比如总览、重命名、合并、删除等等,现在本人把这些操作总结出来,以备后用。
下面我们以一个美国出租车的数据集taxi.csv(以下简称dataset)为例进行总结,由于数据量太大,我们只拿前10000个数据说事,数据集可以免费下载。

dataset <- read.csv("taxi.csv", header = TRUE)[1:10000, ]
一、总览数据

拿到数据集后,我们要先看下数据集是什么样的,有多少行、多少列,某列表式的意义是什么,数据类型是什么,有哪几种数据等等。

1、class()函数

这个函数很常用,就是返回一个变量的数据类型——数据框、列表、向量等等。

> class(dataset)
[1] "data.frame"

噢,dataset这个东西是个数据框。

> class(dataset[, 1])
[1] "integer"

噢,dataset第一列的数据是整型。


2、dim()函数

dim()函数用于查看数据的维度。

> dim(dataset)
[1] 10000    19

结果表示我们的数据集有10000行,也就是10000个样本,19列,也就是19个属性变量。


3、colnames() / names()函数

那都有哪些属性变量呢,我们使用colnames() / names()看一下。

> colnames(dataset)
 [1] "VendorID"              "tpep_pickup_datetime"  "tpep_dropoff_datetime"
 [4] "passenger_count"       "trip_distance"         "pickup_longitude"     
 [7] "pickup_latitude"       "RatecodeID"            "store_and_fwd_flag"   
[10] "dropoff_longitude"     "dropoff_latitude"      "payment_type"         
[13] "fare_amount"           "extra"                 "mta_tax"              
[16] "tip_amount"            "tolls_amount"          "improvement_surcharge"
[19] "total_amount"    

names()函数同样返回这些信息,这些属性的意义我在这就不多说了,数据集有官方解释文档,如下:
在这里插入图片描述


4、str()函数

这个函数返回的信息非常详细,它返回了1、2、3这四个函数的所有结果:数据类型、维度、列名、每列数据类型等等!不过就是看起来有点眼晕。

> str(dataset)
'data.frame':	10000 obs. of  19 variables:
 $ VendorID             : int  2 2 2 2 2 2 2 2 1 1 ...
 $ tpep_pickup_datetime : Factor w/ 551383 levels "2016-01-08T00:00:00Z",..: 70772 72121 73789 74512 81934 82714 83440 86916 1 2 ...
 $ tpep_dropoff_datetime: Factor w/ 553414 levels "2016-01-08T00:01:23Z",..: 71245 73004 73945 74873 81922 82804 84634 86999 490 261 ...
 $ passenger_count      : int  2 1 1 1 1 1 1 1 1 1 ...
 $ trip_distance        : num  1.83 3.18 1.17 5.27 1.14 1.7 5.26 1.04 5.2 2.2 ...
 $ pickup_longitude     : num  -74 -74 -74 -74 -74 ...
 $ pickup_latitude      : num  40.7 40.7 40.8 40.8 40.8 ...
 $ RatecodeID           : int  1 1 1 1 1 1 1 1 1 1 ...
 $ store_and_fwd_flag   : Factor w/ 2 levels "N","Y": 1 1 1 1 1 1 1 1 1 1 ...
 $ dropoff_longitude    : num  -74 -74 -74 -74 -74 ...
 $ dropoff_latitude     : num  40.7 40.8 40.8 40.8 40.7 ...
 $ payment_type         : int  1 1 2 1 2 1 1 1 1 2 ...
 $ fare_amount          : num  10 14.5 7 16.5 6 7.5 21 6.5 18 9.5 ...
 $ extra                : num  0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0 0.5 ...
 $ mta_tax              : num  0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 ...
 $ tip_amount           : num  1.5 3.16 0 2 0 1.76 3 1 2 0 ...
 $ tolls_amount         : num  0 0 0 0 0 0 0 0 0 0 ...
 $ improvement_surcharge: num  0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 0.3 ...
 $ total_amount         : num  12.8 19 8.3 19.8 7.3 ...

5、根据列名获取某一列数据

“$” 这个符号用于取出数据集的某一列全部数据,它返回一个向量,"$"后面一半跟数据集某一列的列名。

> dataset$total_amount
[1]  12.80  18.96   8.30  19.80   7.30  10.56  25.30   8.80  20.80  10.80   6.80
  [12]  11.80   8.80  30.30   7.30  19.80   7.55   6.30   7.30  35.15   9.96  22.80
  [23]   9.95   6.80  24.10   9.80  18.50   5.84  73.34  34.80  17.16  11.75  25.30
  [34]  20.75   9.30  39.30   9.95  11.16  24.30  11.30   9.80   7.80  25.13   8.30
[ reached getOption("max.print") -- omitted 9956 entries ]

我们得到了dataset中total_amount这一列的数据,空间有限,只给我们显示了前44个数据。

> class(dataset$total_amount)
[1] "numeric"

这一列是数值型的。


当然也可以直接用“列名+方括号”访问:

dataset[c("passenger_count", "trip_distance")]
    passenger_count trip_distance
1                 2          1.83
2                 1          3.18
3                 1          1.17
4                 1          5.27
5                 1          1.14
6                 1          1.70
7                 1          5.26
 [ reached 'max' / getOption("max.print") -- omitted 9993 rows ]

取出passenger_count和trip_distance这两列。


6、获取某一行或多行数据

我们知道数据集每一行并没有“行名”,因此我们只能使用下标索引的方式获取行数据,这一点与高级语言C++、Java或Python很像。我们把数据集想象成一个二维矩阵,有m行n列,只不过传统二维矩阵没有列名,而data frame有列名罢了。数据集的下标索引标准为data[m, n],m、n可以是一个数字,表示第几行、第几列,也可以是一个向量,表示哪几行、哪几列,只写m不写n表示取出m行所有列,反之亦同。注意,R语言中下标是从1开始的。

# 取出第一行(包括所有列)
> dataset[1, ]
  VendorID tpep_pickup_datetime tpep_dropoff_datetime passenger_count trip_distance
1        2 2016-01-08T21:29:06Z  2016-01-08T21:42:15Z               2          1.83
  pickup_longitude pickup_latitude RatecodeID store_and_fwd_flag dropoff_longitude
1        -74.00793        40.74529          1                  N         -73.98163
  dropoff_latitude payment_type fare_amount extra mta_tax tip_amount tolls_amount
1          40.7405            1          10   0.5     0.5        1.5            0
  improvement_surcharge total_amount
1                   0.3         12.8

注意,data frame的每一列仍是一个data frame,只不过它只有1行罢了。

# 取出第三列(包括所有行)
> dataset[, 3]
   [1] 2016-01-08T21:42:15Z 2016-01-08T22:11:39Z 2016-01-08T22:27:23Z
   [4] 2016-01-08T22:42:51Z 2016-01-09T00:40:30Z 2016-01-09T00:55:14Z
   [7] 2016-01-09T01:25:55Z 2016-01-09T02:05:33Z 2016-01-08T00:14:11Z
  [10] 2016-01-08T00:09:56Z 2016-01-08T00:03:09Z 2016-01-08T00:07:51Z
  [13] 2016-01-08T00:08:55Z 2016-01-08T00:23:34Z 2016-01-08T00:06:39Z
  [16] 2016-01-08T00:18:08Z 2016-01-08T00:04:23Z 2016-01-08T00:03:16Z
  [19] 2016-01-08T00:06:28Z 2016-01-08T00:34:00Z 2016-01-08T00:06:06Z
[ reached getOption("max.print") -- omitted 9979 entries ]

一列数据构成一个向量,而不是data frame。

# 取出第3行第5列的数据
> dataset[3, 5]
[1] 1.17

单个值。

# 取第1~5行,第4列的数据
# 或简写为 dataset[1:5, 4]
> dataset[c(1:5), 4]
[1] 2 1 1 1 1

它是一个整型向量。

# 取第2、4、5行,第3、4列的数据
```python
> dataset[c(2, 4, 5), c(3, 4)]
 tpep_dropoff_datetime passenger_count
2  2016-01-08T22:11:39Z               1
4  2016-01-08T22:42:51Z               1
5  2016-01-09T00:40:30Z               1

它是一个data frame。


# 从第4行开始一律不要
> subset <- dataset[, -c(4:nrow(dataset))]
> dim(subset)
[1] 10000     3

剩下的数据集保留了全部行,但是只有前三列。


7、table()函数

通俗讲,这个函数可以自动为你完成数据集某列每个元素的频度统计,官方文档是这么说的:

> ?table()
Cross Tabulation and Table Creation

Description

table uses the cross-classifying factors to build a contingency table of the counts at each combination of factor levels.

有道翻译:“table” 使用交叉分类因子来构建每个因子级别组合的计数的列联表。

我们看下效果:

> table(dataset$passenger_count)

   1    2    3    4    5    6 
8109 1381  331  168    6    5 

table是针对某一列起作用的,它返回该列出现的每种数据出现的频数。如上所示,数字1出现了8109次,数据2出现了1381次等等。


二、数据集操作
1、which()函数

这个函数功能很多,我们先讲他的筛选功能。

这个函数返回向量中符合条件的元素下标。

> which(dataset$passenger_count != 2)
   [1]    2    3    4    5    6    7    8    9   10   11   12   13   14   16   17   18
  [17]   20   21   22   23   24   25   26   28   29   30   31   32   33   34   35   38
  [33]   39   40   41   42   46   47   48   49   51   52   53   55   56   57   58   60
  [49]   61   63   64   65   67   69   71   72   73   75   76   77   79   80   81   82
  [65]   83   85   86   87   88   90   91   92   93   95   96   97   98   99  100  101

可以看到,返回的结果均为passenger_count这一列的元素不等于2的下标,那有了这些下标我们就可以取出我们想要的数据。

> subset <- dataset[-which(dataset$passenger_count == 3), ]
> table(subset$passenger_count)

   1    2    4    5    6 
8109 1381  168    6    5 

我们筛选出把passenger_count为3的所有数据(行)去掉后剩余的数据集,再使用table(),发现passenger_count中已经没有为3的数据了。


2、列重命名

我们可以使用colnames(dataframe)来获取数据框的列名,根据这个我们可以对某列重命名。

> colnames(dataset)[5] <- "rename"
> colnames(dataset)
 [1] "VendorID"              "tpep_pickup_datetime"  "tpep_dropoff_datetime"
 [4] "passenger_count"       "rename"                "pickup_longitude"     
 [7] "pickup_latitude"       "RatecodeID"            "store_and_fwd_flag"   
[10] "dropoff_longitude"     "dropoff_latitude"      "payment_type"         
[13] "fare_amount"           "extra"                 "mta_tax"              
[16] "tip_amount"            "tolls_amount"          "improvement_surcharge"
[19] "total_amount"   

我们把第5列重命名为“rename”。


3、增删列

我们可以直接用“数据集$新列名”的方式添加一列。

> newcolumn <- rep(1:10000)
> dataset$added_col <- newcolumn
> colnames(dataset)
 [1] "VendorID"              "tpep_pickup_datetime"  "tpep_dropoff_datetime"
 [4] "passenger_count"       "rename"                "pickup_longitude"     
 [7] "pickup_latitude"       "RatecodeID"            "store_and_fwd_flag"   
[10] "dropoff_longitude"     "dropoff_latitude"      "payment_type"         
[13] "fare_amount"           "extra"                 "mta_tax"              
[16] "tip_amount"            "tolls_amount"          "improvement_surcharge"
[19] "total_amount"          "added_col"  

我们添加了added_col这一列,它是1~10000的整型向量。
也可以使用cbind()函数来按照两个数据集纵向合并的形式添加列。

> dataset <- cbind(dataset, added_col2 = newcolumn)
> colnames(dataset)
 [1] "VendorID"              "tpep_pickup_datetime"  "tpep_dropoff_datetime"
 [4] "passenger_count"       "rename"                "pickup_longitude"     
 [7] "pickup_latitude"       "RatecodeID"            "store_and_fwd_flag"   
[10] "dropoff_longitude"     "dropoff_latitude"      "payment_type"         
[13] "fare_amount"           "extra"                 "mta_tax"              
[16] "tip_amount"            "tolls_amount"          "improvement_surcharge"
[19] "total_amount"          "added_col"             "added_col2"  

将原有数据集dataset和新的一列newcolumn纵向合并,并重新取名为added_col2。


删除列可以使用which函数,根据列名对列进行筛选,然后只要筛选出来的列。

> dataset <- dataset[, -which(colnames(dataset) %in% c("added_col", "added_col2", "added_col3", "added_col4"))]
> colnames(dataset)
 [1] "VendorID"              "tpep_pickup_datetime"  "tpep_dropoff_datetime"
 [4] "passenger_count"       "rename"                "pickup_longitude"     
 [7] "pickup_latitude"       "RatecodeID"            "store_and_fwd_flag"   
[10] "dropoff_longitude"     "dropoff_latitude"      "payment_type"         
[13] "fare_amount"           "extra"                 "mta_tax"              
[16] "tip_amount"            "tolls_amount"          "improvement_surcharge"
[19] "total_amount"    

我们又把之前新增的几列删除了。


当然也可以直接以下标的形式删除列。

> dim(dataset)
[1] 10000    19
> dataset <- dataset[, -5]
> dim(dataset)
[1] 10000    18

我们删除了第5列。


4、增删行

与增删列不同,我们无法根据“行名”来选择行,因此可以使用rbind()来以行为单位横向合并两个数据集的形式增加行。

> newrows <- dataset[4:6, ]
> dataset <- rbind(dataset, newrows)
> dim(dataset)
[1] 10003    18

我们把dataset的第4~6这3行与原数据集横向合并,实现了行的增加。


行的删除就通过下标的形式进行操作。

> dataset <- dataset[-2:4, ]
> dim(dataset)
[1] 10000    18

我们删除了第2~4这3行。


5、数据类型转换

有些数据集导入之后,对于某一列可能不是我们需要的数据类型,因此需要转换。一般的用法是"as.需要的数据类型(列名)"。

我们先看下每列的数据类型

> dataset %>% sapply(class)
             VendorID  tpep_pickup_datetime tpep_dropoff_datetime       passenger_count 
            "integer"              "factor"              "factor"             "integer" 
     pickup_longitude       pickup_latitude            RatecodeID    store_and_fwd_flag 
            "numeric"             "numeric"             "integer"              "factor" 
    dropoff_longitude      dropoff_latitude          payment_type           fare_amount 
            "numeric"             "numeric"             "integer"             "numeric" 
                extra               mta_tax            tip_amount          tolls_amount 
            "numeric"             "numeric"             "numeric"             "numeric" 
improvement_surcharge          total_amount 
            "numeric"             "numeric" 

发现passenger_count这列是integer类型,我们想把它改为因子类型(假设,事实上不需要改)。

> dataset$passenger_count <- factor(dataset$passenger_count, level = c("1", "2", "3", "4", "5", "6"))

> str(dataset$passenger_count)
 Factor w/ 6 levels "1","2","3","4",..: 2 1 1 1 1 1 1 1 1 1 ...

三、高级
1、with()范围限定

with()函数可以限定操作只在某个数据集的范围内起作用,比如我们想计算passenger_count和trip_distance这两列的和,我们可以:

> head(dataset$passenger_count + dataset$trip_distance, 10)
[1] 3.83 4.18 2.17 6.27 2.14 2.70 6.26 2.04 6.20 3.20

但是每次都要输入数据集名称和$符号,很麻烦,可以使用with,使操作限定在dataset数据集内:

> with(dataset, head(passenger_count + trip_distance, 10))
 [1] 3.83 4.18 2.17 6.27 2.14 2.70 6.26 2.04 6.20 3.20

就方便了很多。


2、缺失值(NA)处理

很多时候我们的数据集有很多没有记录的观测点,也就是所谓的缺失值,在R中会显示为NA,那有时候我们想去掉带有NA的一行记录怎么办呢?

在这里插入图片描述

假设我们的数据集叫做data,但凡是出现NA的行我们都想把它删除,可以使用以下语句。

# 首先获取出现过NA的行号下标
NA.index = which(rowSums(is.na(data)) > 0)

# 然后从数据集data中删除或这些下标的行号
new_data <- data[-NA.index, ]

在这里插入图片描述


这样,就消除了全部带有缺失值的观测行,观测值少了当然样本容量也会减小。那有时候我们拟合模型的时候需要大量的样本来控制过拟合,这时候该怎么办呢?我们只需要保证训练集中的response variable也就是ytrain里没有缺失值就好了,而xtrain有没有缺失值我们不关心(有的算法允许带有缺失值),那这个时候只需要把ytrain这一列数据中的NA删掉就好(当然对应xtrain的一行也要删除)。

> length(which(is.na(ytrain) == TRUE))
[1] 358

ytrain中有358个缺失值。

# 获取缺失值下标
> NA.index = which(is.na(ytrain) == TRUE)

# 看看是否获取成功
> length(which(is.na(ytrain[-NA.index]) == TRUE))
[1] 0

# 从ytrain / xtrain中删除相应观测值 / 行
new_ytrain <- ytrain[-NA.index]
new_xtrain <- xtrain[-NA.index, ]

这样,new_ytrain中已经没有了缺失值,而new_xtrain中可能还会有缺失值。

当我们的数据只有一维,也就是vector形式的时候,可以使用以下语句获取含有缺失值的下标:

> NA.index = which(is.na(vector) == TRUE)

当我们的数据有多维,也就是dataframe或matrix形式的时候,可以使用以下语句获取含有缺失值的下标:

> which(rowSums(is.na(data)) > 0)

3、使用正则表达式grep()

学过linux的同学应该都知道,正则表达式在shell命令行中经常用到,其语法灵活易懂,那么在R语言中我们同样可以使用正则表达式来获取我们想获得的信息。具体的正则表达式语法可以参考菜鸟教程:
菜鸟教程——正则表达式

grep()可以返回满足表达式的结果,一般是下标形式。比如我们可以借用grep()来根据列名定位数据集中某列的位置。

# 获取名为“q9”、“q13”的列所在位置
COL.index = NA
num = 1
for(i in c("^q9$", "^q13$"))
{
	COL.index[num] = grep(i, colnames(data))
	num = num + 1
}
> COL.index
[1] 4 8

可以看到,“q9”、“q13”的列分别为于4、8的位置。
当然,要获取列所在位置比这简单的方法很多,前面删除列那一部分就已经讲过,这里只是举个例子。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋之颂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值