洗牌、发牌——操作数据框内的个别值,若从扑克牌最上面开始发牌,需要编写一个可以从数据框中提取第一行数据的函数。
1 .值的选取
要从一个数据框中提取某个值或某一组值,先写出该数据框的名称,在其后紧跟一对中括号
> deck[1,2]
[1] "spades"
第一个索引参数选择数据框中对应的行,第二个索引参数选择相应的列,中间用逗号隔开。
1.1正整数索引
1.deck[i,j]类似于线性代数
会返回deck数据框中第i行第j列的元素;
若要提取多值,使用正整数向量代替单一整数作为索引;
同时 ,也可以将提取出的值作为副本赋给一个R对象
> deck[1,2]
[1] "spades"
> deck[1,c(1,2,3)] #输出第一行整行
face suit value
1 king spades 13
>>new<-deck[1,c(1,2,3)] #赋值给其他R对象
> new
face suit value
1 king spades 13
2.重复值
如果在索引中重复某个数值,R就会在相应索引位置重复提取相应的数据。
下面的命令将deck数据框的第一行数据重复提取两次:
> deck[c(1,1),c(1,2,3)]
face suit value
1 king spades 13
1.1 king spades 13
3.R的记号体系不仅限于数据框
可以用同样的索引语法提取任意R对象中的值
> vec<-c(1,3,4,6,7,4,3)
> vec[1:4]
[1] 1 3 4 6
4.R的索引开始于1
不同于C语言,索引开始于0。如a[0]是数组a中的第一个元素
5.drop=FALSE
如果从一个数据框中提取两列或两列以上的数据,R会返回一个新的数据框;
如果只提取一列,R则会返回一个值;
在这种情况下,如果仍然想返回一个数据框,可以在中括号内添加参数drop=FALSE.;
> deck[1:2,1:2] #两列
face suit
1 king spades
2 queen spades
> deck[1:2,1] #一列
[1] "king" "queen"
> deck[1:2,1,drop=FALSE] #强制转换数据框
face
1 king
2 queen
备注:可以用同样的方法从矩阵或数组中选取一列数据
1.2负整数索引
R返回的元素将不包含负整数索引所对应的元素
如deck[-1,1:3]会返回deck数据框中除了第一行外的所有元素;
而deck[-(2:52),1:3]只返回第一行的元素(返回结果将排除2-52行的元素):
> deck[-(2:52),1:3]
face suit value
1 king spades 13
当需要选取数据框中大部分的行或者列,使用负整数索引将比使用正整数索引更高效
1.3 零索引
返回空对象,没有用
1.4 空格索引
可以使用空格告诉R提取该索引位置所代表维度的所有元素
> deck[1, ]
face suit value
1 king spades 13
1.5 逻辑值索引
在索引时提供一个包含TRUE和FALSE逻辑值的向量(用函数c连接),那么R会匹配索引值为TRUE的行位置(或列位置,取决于索引向量放置的位置)并提取出相应的元素,而忽略FALSE的行位置
> vec<-c(6,1,3,6,10,5)
> vec[c(FALSE,TRUE,FALSE,TRUE,FALSE,TRUE)]
[1] 1 6 5
> deck[1,c(TRUE,TRUE,FALSE)]
face suit
1 king spades
> row<-c(TRUE,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F)
> deck[row, ]
face suit value
1 king spades 13
1.6 名称索引
如果被索引的对象有名称属性,就可以采用待提取元素的名称作为索引值。这种索引方式是从数据框中提取列的常用方法,因为列总会有名称
> deck[1,c("face","suit","value")]
face suit value
1 king spades 13
> deck[ ,"value"] #整个value列
[1] 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5 4 3
[25] 2 1 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5
[49] 4 3 2 1
2 发牌
> deal<-function(deck){deck[1, ]}
> deal
function(deck){deck[1, ]}
> deal()
Error in deal() : 缺少参数"deck",也没有缺省值
#正确的从这里开始
> deal<-function(cards){cards[1, ]} #有点忘记函数的构建方法了
> deal(deck)
face suit value
1 king spades 13
但每次发的都是最上面那一张,因此要洗牌
3 洗牌
每张牌都对应数据框中的一行,要想实现洗牌操作,需要将数据框中的行进行随机重新排列。利用sample函数
> deck2<-deck[1:52, ] #直接提取所有行
> head(deck2)
face suit value
1 king spades 13
2 queen spades 12
3 jack spades 11
4 ten spades 10
5 nine spades 9
6 eight spades 8
> deck2<-deck[c(2,1,3:52), ] #打乱一二行
> head(deck2)
face suit value
2 queen spades 12
1 king spades 13
3 jack spades 11
4 ten spades 10
5 nine spades 9
6 eight spades 8
> random<-sample(1:52,size=52) #52行全打乱
> deck2<-deck[random, ]
> head(deck2)
face suit value
45 eight hearts 8
1 king spades 13
2 queen spades 12
28 queen diamonds 12
47 six hearts 6
38 two diamonds 2
>
练习
#构建一个每次都发第一张牌的函数deal()
> deal<-function(cards){cards[1, ]}
#构建一个洗牌函数wash()
> wash <- function(cards) {
random <- sample(1:52, size = 52)
cards[random, ]
}
#开始使用
> deal(deck)
face suit value
1 king spades 13
> deck2 <- wash(deck) #洗牌
> deal(deck2)
face suit value
41 queen hearts 12
>
4 美元符号与双中括号
1.用美元符号$提取数据框或列表中的值——返回一个向量(可用于计算)
1.1 用法1 ——提取数据框中的值
要提取数据框中的某一列,使用$分割数据框的名称与想要提取的列的名称。注:此处列名称不需要加双引号。
1.2 特征
R会将该列的所有值作为一个向量返回,可以直接用于mean/median等的函数计算
> deck$value #提取value列
[1] 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5 4 3
[25] 2 1 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5
[49] 4 3 2 1
> mean(deck$value) #作为一个向量返回
[1] 7
#直接提取也是作为一个向量返回
> deck[ ,"value"]
[1] 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5 4 3
[25] 2 1 13 12 11 10 9 8 7 6 5 4 3 2 1 13 12 11 10 9 8 7 6 5
[49] 4 3 2 1
> mean(deck[ ,"value"])
[1] 7
1.3 用法2——提取列表中的值
提取一个列表对象中的元素,如果元素有名称,同样可以利用$来完成
1.4 特征
如果通过常规方式提取一个列表对象的元素子集,R会返回一个新的列表对象,其中包含你想要的元素。而用$则会直接返回一个数(向量)
#创建一个列表
> lst<-list(number=c(1,2),logical=TRUE,strings=c("a","b","c"))
> lst
$number
[1] 1 2
$logical
[1] TRUE
$strings
[1] "a" "b" "c"
#正常方法提取元素
> lst[1]
$number
[1] 1 2 #返回一个列表
> lst["number"]
$number
[1] 1 2
> sum(lst[1]) #无法直接用于计算
Error in sum(lst[1]) : 'type'(list)参数不对
利用$提取元素
> lst$number
[1] 1 2 #返回元素
> sum(lst$number) #可直接用于计算
[1] 3
2.双中括号
如果列表中的元素没有名称(或不想使用名称),可以用双中括号代替$,效果相同——返回元素值,而不是它的列表结构;
也可以将这个特性与R的其他索引方式结合起来使用;
> lst$number #只有这里的名称不需要加双引号
[1] 1 2
> lst[[1]]
[1] 1 2
> lst[["number"]]
[1] 1 2