接着上一篇的内容,我们继续介绍数据框的处理。
5. 删除包含缺失值NA
的行
在统计建模中,拥有一个在响应或解释变量中不包含任何缺失值的数据框通常很有用,可以使用na.omit()
函数来达到这个目的。 这是worms
的姊妹版数据框,其中某些值为NA
:
> data <- read.table("C:/data/worms.missing.txt", header=T)
> data
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
1 Nashs.Field 3.6 11 Grassland 4.1 FALSE 4
2 Silwood.Bottom 5.1 NA Arable 5.2 FALSE 7
3 Nursery.Field 2.8 3 Grassland 4.3 FALSE 2
4 Rush.Meadow 2.4 5 Meadow 4.9 TRUE 5
5 Gunness.Thicket 3.8 0 Scrub 4.2 FALSE 6
6 Oak.Mead 3.1 2 Grassland 3.9 FALSE 2
7 Church.Field 3.5 3 Grassland NA NA NA
8 Ashurst 2.1 0 Arable 4.8 FALSE 4
9 The.Orchard 1.9 0 Orchard 5.7 FALSE 9
10 Rookery.Slope 1.5 4 Grassland 5.0 TRUE 7
11 Garden.Wood 2.9 10 Scrub 5.2 FALSE 8
12 North.Gravel 3.3 1 Grassland 4.1 FALSE 1
13 South.Gravel 3.7 2 Grassland 4.0 FALSE 2
14 Observatory.Ridge 1.8 6 Grassland 3.8 FALSE 0
15 Pond.Field 4.1 0 Meadow 5.0 TRUE 6
16 Water.Meadow 3.9 0 Meadow 4.9 TRUE 8
17 Cheapside 2.2 8 Scrub 4.7 TRUE 4
18 Pound.Hill 4.4 2 Arable 4.5 FALSE 5
19 Gravel.Pit NA 1 Grassland 3.5 FALSE 1
20 Farm.Wood 0.8 10 Scrub 5.1 TRUE 3
通过检查,可以看到我们想要去掉第2
行(1
个NA
值)、第7
行(3
个NA
值)和第19
行(1
个NA
值):
> na.omit(data)
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
1 Nashs.Field 3.6 11 Grassland 4.1 FALSE 4
3 Nursery.Field 2.8 3 Grassland 4.3 FALSE 2
4 Rush.Meadow 2.4 5 Meadow 4.9 TRUE 5
5 Gunness.Thicket 3.8 0 Scrub 4.2 FALSE 6
6 Oak.Mead 3.1 2 Grassland 3.9 FALSE 2
8 Ashurst 2.1 0 Arable 4.8 FALSE 4
9 The.Orchard 1.9 0 Orchard 5.7 FALSE 9
10 Rookery.Slope 1.5 4 Grassland 5.0 TRUE 7
11 Garden.Wood 2.9 10 Scrub 5.2 FALSE 8
12 North.Gravel 3.3 1 Grassland 4.1 FALSE 1
13 South.Gravel 3.7 2 Grassland 4.0 FALSE 2
14 Observatory.Ridge 1.8 6 Grassland 3.8 FALSE 0
15 Pond.Field 4.1 0 Meadow 5.0 TRUE 6
16 Water.Meadow 3.9 0 Meadow 4.9 TRUE 8
17 Cheapside 2.2 8 Scrub 4.7 TRUE 4
18 Pound.Hill 4.4 2 Arable 4.5 FALSE 5
20 Farm.Wood 0.8 10 Scrub 5.1 TRUE 3
可以看到第2
,7
,19
行被删掉了。
测试数据框中是否存在缺失值的函数是complete.cases()
:
> complete.cases(data)
[1] TRUE FALSE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE TRUE
[13] TRUE TRUE TRUE TRUE TRUE TRUE FALSE TRUE
因此你也可以通过下列方式删除NA
行:
> data[complete.cases(data), ]
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
1 Nashs.Field 3.6 11 Grassland 4.1 FALSE 4
3 Nursery.Field 2.8 3 Grassland 4.3 FALSE 2
4 Rush.Meadow 2.4 5 Meadow 4.9 TRUE 5
5 Gunness.Thicket 3.8 0 Scrub 4.2 FALSE 6
6 Oak.Mead 3.1 2 Grassland 3.9 FALSE 2
8 Ashurst 2.1 0 Arable 4.8 FALSE 4
9 The.Orchard 1.9 0 Orchard 5.7 FALSE 9
10 Rookery.Slope 1.5 4 Grassland 5.0 TRUE 7
11 Garden.Wood 2.9 10 Scrub 5.2 FALSE 8
12 North.Gravel 3.3 1 Grassland 4.1 FALSE 1
13 South.Gravel 3.7 2 Grassland 4.0 FALSE 2
14 Observatory.Ridge 1.8 6 Grassland 3.8 FALSE 0
15 Pond.Field 4.1 0 Meadow 5.0 TRUE 6
16 Water.Meadow 3.9 0 Meadow 4.9 TRUE 8
17 Cheapside 2.2 8 Scrub 4.7 TRUE 4
18 Pound.Hill 4.4 2 Arable 4.5 FALSE 5
20 Farm.Wood 0.8 10 Scrub 5.1 TRUE 3
可以看出这种方式稍微复杂一些。
因为一个或多个变量可能会贡献大部分缺失值,因此值得去单独检查各个变量。在建模过程中,删掉具有很多缺失值的变量,而保留那些具有少量缺失值的变量。可以使用summary()
函数来计算数据框中每个变量的缺失值数目,或者将apply()
与is.na()
函数一起使用求出每个变量中的缺失值数目:
> summary(data)
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
Ashurst : 1 Min. :0.800 Min. : 0.000 Arable :3 Min. :3.500 Mode :logical Min. :0.000
Cheapside : 1 1st Qu.:2.150 1st Qu.: 0.500 Grassland:9 1st Qu.:4.100 FALSE:13 1st Qu.:2.000
Church.Field: 1 Median :3.100 Median : 2.000 Meadow :3 Median :4.700 TRUE :6 Median :4.000
Farm.Wood : 1 Mean :2.995 Mean : 3.579 Orchard :1 Mean :4.574 NA's :1 Mean :4.421
Garden.Wood : 1 3rd Qu.:3.750 3rd Qu.: 5.500 Scrub :4 3rd Qu.:5.000 3rd Qu.:6.500
Gravel.Pit : 1 Max. :5.100 Max. :11.000 Max. :5.700 Max. :9.000
(Other) :14 NA's :1 NA's :1 NA's :1 NA's :1
> apply(is.na(data),2,sum)
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
0 1 1 0 1 1 1
可以看到,对于这个数据框,所有变量最多只有一个缺失值。
在执行下面操作之前,您需要仔细考虑,但是在某些情况下,您可能希望将缺失值NA
替换为0
(或其他值,比如平均值)。data
数据框包含5
个缺失值,将所有NA
替换为0
的方法为:
> data
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
1 Nashs.Field 3.6 11 Grassland 4.1 FALSE 4
2 Silwood.Bottom 5.1 NA Arable 5.2 FALSE 7
3 Nursery.Field 2.8 3 Grassland 4.3 FALSE 2
4 Rush.Meadow 2.4 5 Meadow 4.9 TRUE 5
5 Gunness.Thicket 3.8 0 Scrub 4.2 FALSE 6
6 Oak.Mead 3.1 2 Grassland 3.9 FALSE 2
7 Church.Field 3.5 3 Grassland NA NA NA
8 Ashurst 2.1 0 Arable 4.8 FALSE 4
9 The.Orchard 1.9 0 Orchard 5.7 FALSE 9
10 Rookery.Slope 1.5 4 Grassland 5.0 TRUE 7
11 Garden.Wood 2.9 10 Scrub 5.2 FALSE 8
12 North.Gravel 3.3 1 Grassland 4.1 FALSE 1
13 South.Gravel 3.7 2 Grassland 4.0 FALSE 2
14 Observatory.Ridge 1.8 6 Grassland 3.8 FALSE 0
15 Pond.Field 4.1 0 Meadow 5.0 TRUE 6
16 Water.Meadow 3.9 0 Meadow 4.9 TRUE 8
17 Cheapside 2.2 8 Scrub 4.7 TRUE 4
18 Pound.Hill 4.4 2 Arable 4.5 FALSE 5
19 Gravel.Pit NA 1 Grassland 3.5 FALSE 1
20 Farm.Wood 0.8 10 Scrub 5.1 TRUE 3
data[is.na(data)] <- 0
> data
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
1 Nashs.Field 3.6 11 Grassland 4.1 0 4
2 Silwood.Bottom 5.1 0 Arable 5.2 0 7
3 Nursery.Field 2.8 3 Grassland 4.3 0 2
4 Rush.Meadow 2.4 5 Meadow 4.9 1 5
5 Gunness.Thicket 3.8 0 Scrub 4.2 0 6
6 Oak.Mead 3.1 2 Grassland 3.9 0 2
7 Church.Field 3.5 3 Grassland 0.0 0 0
8 Ashurst 2.1 0 Arable 4.8 0 4
9 The.Orchard 1.9 0 Orchard 5.7 0 9
10 Rookery.Slope 1.5 4 Grassland 5.0 1 7
11 Garden.Wood 2.9 10 Scrub 5.2 0 8
12 North.Gravel 3.3 1 Grassland 4.1 0 1
13 South.Gravel 3.7 2 Grassland 4.0 0 2
14 Observatory.Ridge 1.8 6 Grassland 3.8 0 0
15 Pond.Field 4.1 0 Meadow 5.0 1 6
16 Water.Meadow 3.9 0 Meadow 4.9 1 8
17 Cheapside 2.2 8 Scrub 4.7 1 4
18 Pound.Hill 4.4 2 Arable 4.5 0 5
19 Gravel.Pit 0.0 1 Grassland 3.5 0 1
20 Farm.Wood 0.8 10 Scrub 5.1 1 3
6. 使用order
和!duplicated
删掉假重复行
在这个比较复杂的示例中,要求为每种植被类型提取一条记录,并且该记录在每种植被类型中具有最大蠕虫密度。为此,需要执行两个步骤:首先使用order(Worm.density, decreasing = T)
对数据框中的所有行按照蠕虫密度进行降排序,并赋予给新变量new
;然后对于每种植被类型,选择没有重复的行:
> worms <- read.table("C:/data/worms.txt",header=T)
> attach(worms)
> new <- worms[order(Worm.density, decreasing = T), ]
> new[!duplicated(new$Vegetation), ]
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
9 The.Orchard 1.9 0 Orchard 5.7 FALSE 9
11 Garden.Wood 2.9 10 Scrub 5.2 FALSE 8
16 Water.Meadow 3.9 0 Meadow 4.9 TRUE 8
2 Silwood.Bottom 5.1 2 Arable 5.2 FALSE 7
10 Rookery.Slope 1.5 4 Grassland 5.0 TRUE 7
7. 混合方向的复杂排序
有时会有多个排序变量,但是必须按相反的方向对变量进行排序。 在此示例中,首先根据植被类型的字母顺序对数据框进行排序,然后在每种植被类型内按蠕虫密度以降序进行排序(首先是最高密度)。 这里可以用order()
函数,但在Worm.density
前面放一个减号-
,如下所示:
> worms[order(Vegetation, -Worm.density), ]
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
2 Silwood.Bottom 5.1 2 Arable 5.2 FALSE 7
18 Pound.Hill 4.4 2 Arable 4.5 FALSE 5
8 Ashurst 2.1 0 Arable 4.8 FALSE 4
10 Rookery.Slope 1.5 4 Grassland 5.0 TRUE 7
1 Nashs.Field 3.6 11 Grassland 4.1 FALSE 4
7 Church.Field 3.5 3 Grassland 4.2 FALSE 3
3 Nursery.Field 2.8 3 Grassland 4.3 FALSE 2
6 Oak.Mead 3.1 2 Grassland 3.9 FALSE 2
13 South.Gravel 3.7 2 Grassland 4.0 FALSE 2
12 North.Gravel 3.3 1 Grassland 4.1 FALSE 1
19 Gravel.Pit 2.9 1 Grassland 3.5 FALSE 1
14 Observatory.Ridge 1.8 6 Grassland 3.8 FALSE 0
16 Water.Meadow 3.9 0 Meadow 4.9 TRUE 8
15 Pond.Field 4.1 0 Meadow 5.0 TRUE 6
4 Rush.Meadow 2.4 5 Meadow 4.9 TRUE 5
9 The.Orchard 1.9 0 Orchard 5.7 FALSE 9
11 Garden.Wood 2.9 10 Scrub 5.2 FALSE 8
5 Gunness.Thicket 3.8 0 Scrub 4.2 FALSE 6
17 Cheapside 2.2 8 Scrub 4.7 TRUE 4
20 Farm.Wood 0.8 10 Scrub 5.1 TRUE 3
仅当对数字变量进行排序时,才使用减号。 对于因子变量,可以使用rank()
函数使因子数字化,如下所示:
> worms[order(-rank(Vegetation), -Worm.density), ]
Field.Name Area Slope Vegetation Soil.pH Damp Worm.density
11 Garden.Wood 2.9 10 Scrub 5.2 FALSE 8
5 Gunness.Thicket 3.8 0 Scrub 4.2 FALSE 6
17 Cheapside 2.2 8 Scrub 4.7 TRUE 4
20 Farm.Wood 0.8 10 Scrub 5.1 TRUE 3
9 The.Orchard 1.9 0 Orchard 5.7 FALSE 9
16 Water.Meadow 3.9 0 Meadow 4.9 TRUE 8
15 Pond.Field 4.1 0 Meadow 5.0 TRUE 6
4 Rush.Meadow 2.4 5 Meadow 4.9 TRUE 5
10 Rookery.Slope 1.5 4 Grassland 5.0 TRUE 7
1 Nashs.Field 3.6 11 Grassland 4.1 FALSE 4
7 Church.Field 3.5 3 Grassland 4.2 FALSE 3
3 Nursery.Field 2.8 3 Grassland 4.3 FALSE 2
6 Oak.Mead 3.1 2 Grassland 3.9 FALSE 2
13 South.Gravel 3.7 2 Grassland 4.0 FALSE 2
12 North.Gravel 3.3 1 Grassland 4.1 FALSE 1
19 Gravel.Pit 2.9 1 Grassland 3.5 FALSE 1
14 Observatory.Ridge 1.8 6 Grassland 3.8 FALSE 0
2 Silwood.Bottom 5.1 2 Arable 5.2 FALSE 7
18 Pound.Hill 4.4 2 Arable 4.5 FALSE 5
8 Ashurst 2.1 0 Arable 4.8 FALSE 4
您不太可能希望根据逻辑操作来选择列,但这是完全可能的。假设由于某种原因你想选择的列包含大写'S'
字符。可以使用R中的grep()
,它返回字符串向量中哪些字符串包含大写字母S
的下标。数据框的变量名称是通过names()
函数获得的:
> names(worms)
[1] "Field.Name" "Area" "Slope" "Vegetation"
[5] "Soil.pH" "Damp" "Worm.density"
因此,我们希望函数grep()
挑选变量编号3
和5
,因为它们是唯一包含大写字母S
的变量:
> grep("S",names(worms))
[1] 3 5
最后,我们可以使用这些数字作为下标[ ,c(3,5)]
来选择第3
和第5
列:
> worms[ ,grep("S", names(worms))]
Slope Soil.pH
1 11 4.1
2 2 5.2
3 3 4.3
4 5 4.9
5 0 4.2
6 2 3.9
7 3 4.2
8 0 4.8
9 0 5.7
10 4 5.0
11 10 5.2
12 1 4.1
13 2 4.0
14 6 3.8
15 0 5.0
16 0 4.9
17 8 4.7
18 2 4.5
19 1 3.5
20 10 5.1
8. 具有行名而不是行号的数据框
您可以通过更改read.table
函数的参数来禁止创建行号,并为每行分配唯一名称。worms
数据框的第一列变量是田地的名称,而其它变量是在这块田地测量的量。之前,我们一直将第一列当作第一个变量来读取。现在我们将第一列当成行名:
> worms2 <- read.table("C:/data/worms.txt",header=T, row.names=1)
> worms2
Area Slope Vegetation Soil.pH Damp Worm.density
Nashs.Field 3.6 11 Grassland 4.1 FALSE 4
Silwood.Bottom 5.1 2 Arable 5.2 FALSE 7
Nursery.Field 2.8 3 Grassland 4.3 FALSE 2
Rush.Meadow 2.4 5 Meadow 4.9 TRUE 5
Gunness.Thicket 3.8 0 Scrub 4.2 FALSE 6
Oak.Mead 3.1 2 Grassland 3.9 FALSE 2
Church.Field 3.5 3 Grassland 4.2 FALSE 3
Ashurst 2.1 0 Arable 4.8 FALSE 4
The.Orchard 1.9 0 Orchard 5.7 FALSE 9
Rookery.Slope 1.5 4 Grassland 5.0 TRUE 7
Garden.Wood 2.9 10 Scrub 5.2 FALSE 8
North.Gravel 3.3 1 Grassland 4.1 FALSE 1
South.Gravel 3.7 2 Grassland 4.0 FALSE 2
Observatory.Ridge 1.8 6 Grassland 3.8 FALSE 0
Pond.Field 4.1 0 Meadow 5.0 TRUE 6
Water.Meadow 3.9 0 Meadow 4.9 TRUE 8
Cheapside 2.2 8 Scrub 4.7 TRUE 4
Pound.Hill 4.4 2 Arable 4.5 FALSE 5
Gravel.Pit 2.9 1 Grassland 3.5 FALSE 1
Farm.Wood 0.8 10 Scrub 5.1 TRUE 3
请注意,Field.Name
列不再以变量名开头,它不是变量了,是行名称了,并且行号没有了。
9. 用另一种对象来创建数据框
我们已经看到,在R中创建数据帧的最简单方法是使用read.table
函数从外部文件读取数据表。另外,您可以通过使用data.frame()
函数将多个矢量绑定在一起来创建数据框。这是3
个相同长度的向量:
x <- runif(10)
y <- letters[1:10]
z <- sample(c(rep(T,5),rep(F,5)))
要将它们放入一个名为new
的数据框中,只需键入:
> new <- data.frame(y,z,x)
> new
y z x
1 a FALSE 0.71062764
2 b TRUE 0.30570981
3 c FALSE 0.09079743
4 d FALSE 0.09158113
5 e TRUE 0.65112670
6 f FALSE 0.30225698
7 g FALSE 0.69819712
8 h TRUE 0.65980129
9 i TRUE 0.09676492
10 j TRUE 0.37905503
请注意,列的顺序仅由data.frame()
函数中指定的向量名称顺序(从左到右)控制。
在下一个示例中,我们根据泊松分布创建一个随机整数计数表,然后将该表转换为数据框。首先,我们创建一个表(table
)对象:
> y <- rpois(1500,1.5)
> table(y)
y
0 1 2 3 4 5 6 7
326 505 355 196 83 28 6 1
现在,使用as.data.frame()
函数可以很容易地将此表对象转换为具有两个变量(特征值和频数)的数据框:
> short <- as.data.frame(table(y))
> short
y Freq
1 0 326
2 1 505
3 2 355
4 3 196
5 4 83
6 5 28
7 6 6
8 7 1
今天的内容就到此为止,下一篇文章将继续介绍有关数据框的处理。
感谢您的阅读!想了解更多有关技巧,请关注我的微信公众号“R语言和Python学堂”,我将定期更新相关文章。

网友评论