R语言入门学习笔记(三)

R语言入门学习笔记(三)



前言

目前为止,我们学习了R对象,这可以用于暂存所需要处理的数据。但是,在数据分析的过程中,我们可能随时需要调取这些R对象中的部分数据进行分析,我们要如何对这些数据进行选择和处理呢?这次的学习将会学习到R中取值以及修改数值的方法,这样我们就可以对R中的数据进行提取和修改了。

一、值的选取

R中有一套索引体系,可以用于提取R对象中的值。如下所示

data[x, y]

可以从名为data的数据框中提取第x行,第y列的数值。对于R来说,在编写索引的时候,有6种方式可供选择:正整数、负整数、零、空格、逻辑值和名称。

1.正整数

正整数索引方式如同上面提到的,xy均为正整数的情况下,索引的为x行y列的数值。需要注意的是R的索引是从1开始的(与python从0开始不同)。这种索引可以同时对多行多列进行索引:

df <- data.frame(A = c(1, 1, 1), B = c(2, 2, 2), C = c(3, 3, 3))
df
#>   A B C
#> 1 1 2 3
#> 2 1 2 3
#> 3 1 2 3
df[1, 2]
#> [1] 2
df[1, 2, drop = FALSE]
#>   B
#> 1 2
df[c(1:3), 1]
#> [1] 1 1 1
df[1, c(1:3)]
#>   A B C
#> 1 1 2 3
df[c(1, 1), c(1:3)]
#>     A B C
#> 1   1 2 3
#> 1.1 1 2 3

这里注意,在只索引1列的时候会返回一个向量,在索引2列及以上的时候会返回数据框,如果想要都返回数据框,可以在索引的时候添加参数drop = FALSE。另外,如果在索引种重复某个数值,R就会在相应位置重复提取相同的数据,然后在返回值中重复出现。
这种索引方法不只是适用于数据框,可以适用于任何R对象,只要该对象在相应维度有索引值即可。

2.负整数

负整数的索引值是不包含的意思。R对象将不返回负整数索引所对应的元素,可以将负号看作减的意思。

df[-1, -1]
#>   B C
#> 2 2 3
#> 3 2 3

不能在同一个索引位置同时出现正负索引,但不同索引位置是可以的。

3.零

零索引会返回空对象,实际并没有什么意义。

df[0, 1]
#> numeric(0)
df[0, 0]
#> data frame with 0 columns and 0 rows

4.空格

如果在某个索引位置不键入任何数字,或者键入一个空格,则会索引该位置对应的所有数据。

5.逻辑值

逻辑值为TRUEFALSE,将会索引所有TRUE元素对应的位置的值。索引数量与对应位置元素的数量相同时,会按照逻辑值对应进行索引。索引数量小于对应位置元素的数量时,会自动重复索引对该位置元素进行索引。索引数量大于对应位置元素的数量应该避免。

# 索引长度少于被索引元素长度
df[1, T]
#>   A B C
#> 1 1 2 3
df[1, c(T,F)]
#>   A C
#> 1 1 3
vec <- c(1, 2, 3, 4, 5, 6)
vec[c(T,F)]
#> [1] 1 3 5

# 索引长度超出被索引元素长度
vec[c(T,F,F,T,T,F,T,T,F)]
#> [1]  1  4  5 NA NA
df[1, c(T,F,T,T,T)]
#> Error in `[.data.frame`(df, 1, c(T, F, T, T, T)) : 选择了未定义的列

6.名称

如果R对象有名称属性(关于名称属性,请移步至R语言入门学习笔记(二)),就可以根据对应位置的名称进行索引。

df[1, "A"]
#> [1] 1
df[, c("A", "C")]
#>   A C
#> 1 1 3
#> 2 1 3
#> 3 1 3

7.$与[[ ]]

R中还有另外的索引体系:$[[ ]]。$用于提取数据框或列表中对象中的值。
数据框中可以直接用$索引某列的值:

df$A
#> [1] 1 1 1

它会返回一个向量,向量便于直接进行计算。

mean(df$A)
#> [1] 1

在对列表索引的方法类似:

lst <- list(num = c(1:20), word = "R语言真好玩", log = c(TRUE, FALSE))
lst$num
#> [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

在介绍[[ ]]的索引方式,首先看看[]索引:

lst[2]
#> $word
#> [1] "R语言真好玩"
typeof(lst[2])
#> [1] "list"

此时经过索引得到的是一个只包含了一个字符串的list。如果想要直接索引到内部的字符串就要用到双中括号了:

lst[[2]]
#> [1] "R语言真好玩"
typeof(lst[[2]])
#> [1] "character"
lst$word
#> [1] "R语言真好玩"

双中括号在列表没有名字属性的时候可以代替$符号使用。
引用书中的一幅图来梳理一下中括号间的索引关系:
图1:将列表对象想象成一列火车,索引方法如图

二、数值更改

在进行数值更改前,最好留好数据副本,以免更改的面目全非后不能恢复。

1.直接改值

可以使用R的索引体系直接在数据上进行单独或批量的改值。

vec[1] <- 100
vec
#> [1] 100   2   3   4   5   6

vec[c(1, 3, 5)] <- c(0, 0, 0)
vec
#> [1] 0 2 0 4 0 6

vec[c(1, 3, 5)] <- vec[c(1, 3, 5)] + 1
vec
#> [1] 1 2 1 4 1 6

另外,还可以创建原来不存在的新值:

vec[7] <- 100
vec
#> [1]   1   2   1   4   1   6 100

vec <- vec[-7]
vec
#> [1]   1   2   1   4   1   6

如果想要数据框中删除某些列,可以将其赋值为NULL

df[,"C"] <- NULL
# df$C <- NULL也可以
df
#>   A B
#> 1 1 2
#> 2 1 2
#> 3 1 2

2.逻辑值取子集

在R的索引中可以利用逻辑值进行对应的索引,从而筛选出想要的数据。但是要打出那么多的TRUEFALSE也不现实。幸运的是,不需要这么做也没有意义,可以使用逻辑测试来生成逻辑值。
在R中有如下逻辑测试方法:

运算符语法解释
>a > ba是否大于b?
<a < ba是否小于b?
>=a >= ba是否大于等于b?
<=a <= ba是否小于等于b?
==a == ba是否等于b?
!=a != ba是否不等于b?
%in%a %in% c(a, b, c)a是否含于c(a, b, c)?

除了%in%外,其他运算符都是进行左右的一一对比:

1 > c(0, 1, 2)
#> [1]  TRUE FALSE FALSE
c(1, 2, 3) == c(3, 2, 1)
#> [1] FALSE  TRUE FALSE

这些运算符都与其他算术运算符遵循的规则一致,即如果运算符两个向量的长度不等,R会重读较短的向量以达到较长的向量(见R语言入门学习笔记(一)):

1 > c(0, 1, 2)
#> [1]  TRUE FALSE FALSE
# 等价于c(1, 1, 1) > c(0, 1, 2)

c(1, 2, 3, 4) == c(1, 2)
#> [1]  TRUE  TRUE FALSE FALSE
# 等价于c(1, 2, 3, 4) == c(1, 2, 1, 2)

%in%运算符则是将左侧每个元素单独与右侧整体进行对比得到判断,得到逻辑值个数与左侧元素个数相同:

c(1, 5) %in% c(0, 1, 2)
#> [1]  TRUE FALSE

注意不要将 = == 弄混,= 是赋值符号相当于 <-,逻辑判断需要用 ==
逻辑值取值法的应用十分广泛,比如:

df <- data.frame(A = c(1, 3, 5), B = c(2, 4, 6), C = c(1, 1, 3))
df$C == 1
#> [1]  TRUE  TRUE FALSE

可以通过sum()函数统计其中TRUE逻辑值的个数,因为此时计算时会触发R的强制转换,将逻辑值转换为数字,TRUE会被转换为1。这对快速了解数据特征有帮助。

sum(df$C == 1)
#> [1] 2

在逻辑值取值后就可以将其作为一个索引来选取一些数据,然后通过赋值,对选到的数据进行更改:

# 选择C列中值为1的数据对应的B列的值(逻辑值取值)
df$B[df$C == 1]
#> [1] 2 4

# 看一眼原始df数据框理解一下
df
#>   A B C
#> 1 1 2 1
#> 2 3 4 1
#> 3 5 6 3

# 通过赋值修改B列的值
df$B[df$C == 1] <- 10
df
#>   A  B C
#> 1 1 10 1
#> 2 3 10 1
#> 3 5  6 3

3.布尔运算符

如果需要将逻辑运算符组合起来就要用到布尔运算符了,这是一组关于与和或(等等)的运算符。它们将最终输出一个逻辑值。
R中的布尔运算符如下:

运算符语法解释
&event1 & event2event1和event2是否同时为真?
|event1 | event2event1和event2是否至少一个为真?
xorxor(event1, event2)event1和event2是否只有一个为真?
!!event1event1是否为假?(event1的反结果)
anyany(event1, event2, event3)所有事件中是否至少有一个为真?
allall(event1, event2, event3)所有时间是否同时为真?

遇到布尔逻辑符时,R会先计算所有事件的逻辑值,然后根据布尔运算逻辑组合在进行逻辑值计算。

三、缺失信息

在操作R数据中值的时候,有时会遇到缺失值。这些值可能是由于丢失或者并未测量等等原因而不存在了。
在R中会使用NA来存储缺失值,R中处理缺失值的方法与我们是不一样的。比如1+NA在R中会返回NA作为结果,因为缺失值不能用0简单替代。在进行逻辑测试的时候NA == 1同样会返回NA

1.na.rm

缺失值的存在会比较棘手,因为在进行统计分析时,由于NA值得存在会使得结果也是NA。但这可能并不是我们期待得结果。大多数R函数都有一个可选参数na.rm它表示移除NA值,可以通过添加na.rm = TRUE让R在计算时忽略NA。

2.is.na

有些时候,可能想要通过逻辑测试来定位NA。但是NA == NA的结果也是NA。

c(1, 2, 3, NA) == NA
#> [1] NA NA NA NA

因此R提供了is.na函数来测试某个值是否为NA。

is.na(NA)
#> TRUE
is.na(c(1, 2, 3, NA))
#> [1] FALSE FALSE FALSE  TRUE

总结

通过本节学习,我们学会了在R中定向的索引数据。可以使用多种方式对R对象中元素进行索引。进行索引后,我们就可以使用赋值函数对R对象中的数据进行修改,注意有需要时在修改前保存数据副本。为了更好的对数据进行定向修改,学习了逻辑值取子集的方法。另外,在处理数据的过程中,缺失值会是我们的一个困扰,所以在R中也提供了一些特定的函数来处理这些值。

  • 23
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值