《Cookbook for R》 Manipulating Data ~ General
Sorting 排序
1、vectors 向量
# 先随机生成一组向量
v <- sample(101:110)# 排序sort()
sort(v)
#> [1] 101 102 103 104 105 106 107 108 109 110# 反向排序
sort(v, decreasing=TRUE)
#> [1] 110 109 108 107 106 105 104 103 102 101
2、data frames 数据框
要对一个或多个列上的数据帧进行排序,可以使用 plyr
包中的 arrange()
# 生成一个数据框
df <- data.frame (id=1:4,weight=c(20,27,24,22),size=c("small", "large", "medium", "large"))
dflibrary(plyr)# 按weight这一列排序
arrange(df, weight) # 使用arrange函数
df[ order(df$weight), ] # 使用R自带函数
#> id weight size
#> 1 1 20 small
#> 2 4 22 large
#> 3 3 24 medium
#> 4 2 27 large# 按size排序,再按weight排序
arrange(df, size, weight)
df[ order(df$size, df$weight), ]
#> id weight size
#> 4 4 22 large
#> 2 2 27 large
#> 3 3 24 medium
#> 1 1 20 small# 按所有列进行排序,列的顺序从左到右
df[ do.call(order, as.list(df)), ]
Note:size
这一列是因子,按因子水平的顺序排序;在这种情况下,级别是自动分配的(在创建数据框时),因此large
是第一个,small
是最后一个。
3、reverse sort 反向排序
排序的整体顺序可以用参数 decreasing=TRUE
颠倒
若要反转特定列的方向,该方法取决于数据类型:
- Numbers:在变量名前面加上
-
,例如df[ order(-df$weight), ]
; - Factors:转换为整数,并在变量名前面加上
-
,例如df[ order(-xtfrm(df$size)), ]
; - Characters: 没有一个简单的方法可以做到这一点。一种方法是先转换为因子,然后如上所述进行排序
# 按weight这一列反向排序
arrange(df, -weight) # 使用arrange函数
df[ order(df$weight, decreasing=TRUE), ] # 使用R自带函数
df[ order(-df$weight), ] # 使用R自带函数
#> id weight size
#> 2 2 27 large
#> 3 3 24 medium
#> 4 4 22 large
#> 1 1 20 small# 按 size (increasing), 然后按 weight (decreasing)
arrange(df, size, -weight)
df[ order(df$size, -df$weight), ]
#> id weight size
#> 2 2 27 large
#> 4 4 22 large
#> 3 3 24 medium
#> 1 1 20 small# 按 size (decreasing), 然后按 weight (increasing)
# R自带函数 xtfrm() ,用于生成一个数字向量
arrange(df, -xtfrm(size), weight) # Use arrange from plyr package
df[ order(-xtfrm(df$size), df$weight), ] # Use built-in R functions
#> id weight size
#> 1 1 20 small
#> 3 3 24 medium
#> 4 4 22 large
#> 2 2 27 large
Randomizing order 随机化排序
当你想随机化排序时
# 先创造一个向量
v <- 11:20# 使向量随机化
v <- sample(v)# 再创建一个数据框
data <- data.frame(label=letters[1:5], number=11:15)
data
#> label number
#> 1 a 11
#> 2 b 12
#> 3 c 13
#> 4 d 14
#> 5 e 15# 使数据框随机化
data <- data[sample(1:nrow(data)), ]
data
#> label number
#> 5 e 15
#> 2 b 12
#> 4 d 14
#> 3 c 13
#> 1 a 11
要使随机化可重复,应该为随机数生成器设置种子
Converting between vector types 向量类型转换
在数字向量、字符向量和因子之间进行转换
从这个数字向量 n
开始:
n <- 10:14
n
#> [1] 10 11 12 13 14
要将数字向量转换为其他两种类型:
# Numeric 数字型 to Character 字符型
c <- as.character(n)# Numeric 数字型 to Factor 因子型
f <- factor(n)
# 10 11 12 13 14
要将字符向量转换为其他两个:
# Character 字符型 to Numeric 数字型
as.numeric(c)
#> [1] 10 11 12 13 14# Character 字符型 to Factor 因子型
factor(c)
#> [1] 10 11 12 13 14
#> Levels: 10 11 12 13 14
将因子转换为字符向量很简单:
# Factor to Character
as.character(f)
#> [1] "10" "11" "12" "13" "14"
但把因子转为数值型则有点棘手
如果你只是用 as.numeric
转换它,它会给你给予因子的数字编码,这可能不是你想要的结果
as.numeric(f)
#> [1] 1 2 3 4 5# 另一种得到数字编码的方式
unclass(f)
#> [1] 1 2 3 4 5
#> attr(,"levels")
#> [1] "10" "11" "12" "13" "14"
将文本内容转换为数字的方法是:
首先将其转换为字符,然后转换为数字向量
# Factor to Numeric
as.numeric(as.character(f))
#> [1] 10 11 12 13 14
Finding and removing duplicate records 查找和删除重复记录
从向量或数据框中查找和/或删除重复条目
1、对向量
# 设置随机种子
# 生成一个向量,取整数部分
set.seed(158)
x <- round(rnorm(20, 10, 5))
x
#> [1] 14 11 8 4 12 5 10 10 3 3 11 6 0 16 8 10 8 5 6 6# duplicate()判断是否有重复
# 某元素第一次出现的位置返回FALSE,第二次出现的位置返回TRUE
duplicated(x)
#> [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE TRUE FALSE FALSE FALSE
#> [15] TRUE TRUE TRUE TRUE TRUE TRUE# 利用返回的逻辑值取子集
x[duplicated(x)]
#> [1] 10 3 11 8 10 8 5 6 6
# 因为6、10、8出现了3次,后两次都是TRUE
# 所以会被选出来2个# 用unique()去重复
# unique()默认保留第一次出现的元素
unique(x[duplicated(x)])
#> [1] 10 3 11 8 5 6# 用unique()给原始x去重复
unique(x)
#> [1] 14 11 8 4 12 5 10 3 6 0 16
# !逆转逻辑值
x[!duplicated(x)]
#> [1] 14 11 8 4 12 5 10 3 6 0 16
2、对数据框
# 示例
df <- read.table(header=TRUE, text='label valueA 4B 3C 6B 3B 1A 2A 4A 4
')# 判断是否有重复的行?
duplicated(df)
#> [1] FALSE FALSE FALSE TRUE FALSE FALSE TRUE TRUE# 找出重复的行
df[duplicated(df),]
#> label value
#> 4 B 3
#> 7 A 4
#> 8 A 4# 重复条目去重
unique(df[duplicated(df),])
#> label value
#> 4 B 3
#> 7 A 4# 原始数据去重复,返回去掉重复的数据框
unique(df)
#> label value
#> 1 A 4
#> 2 B 3
#> 3 C 6
#> 5 B 1
#> 6 A 2
df[!duplicated(df),]
#> label value
#> 1 A 4
#> 2 B 3
#> 3 C 6
#> 5 B 1
#> 6 A 2
Comparing vectors or factors with NA 将向量或因子与NA进行比较
想要比较两个向量或因子
但希望与 NA
比较的结果报告为 TRUE
或 FALSE
(而不是 NA
)
假如你有这样的数据框
由两列布尔向量(逻辑)组成,且内含 NA
df <- data.frame( a=c(TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,NA,NA,NA),b=c(TRUE,FALSE,NA,TRUE,FALSE,NA,TRUE,FALSE,NA))
df
#> a b
#> 1 TRUE TRUE
#> 2 TRUE FALSE
#> 3 TRUE NA
#> 4 FALSE TRUE
#> 5 FALSE FALSE
#> 6 FALSE NA
#> 7 NA TRUE
#> 8 NA FALSE
#> 9 NA NA
默认情况,当比较两个包含 NA
值的向量或因子时,
只要原始项中的任一项为 NA
,结果向量将具有 NA
。
# 两列相比,相同返回TRUE
df$a == df$b
#> [1] TRUE FALSE NA FALSE TRUE NA NA NA NA# 将结果新增一列到数据框中
data.frame(df, isSame = (df$a==df$b))
#> a b isSame
#> 1 TRUE TRUE TRUE
#> 2 TRUE FALSE FALSE
#> 3 TRUE NA NA
#> 4 FALSE TRUE FALSE
#> 5 FALSE FALSE TRUE
#> 6 FALSE NA NA
#> 7 NA TRUE NA
#> 8 NA FALSE NA
#> 9 NA NA NA
与 NA
比较的函数:
这个函数本质上将 NA
视为另一个值。
如果两个向量中的一个项都是 NA
,则它报告该项的 TRUE
;
如果该项在一个向量中是 NA
,则它报告 FALSE
;
所有其他比较(非 NA
项之间)的行为相同。
# 只要内容相同就返回TRUE
compareNA <- function(v1,v2) {same <- (v1 == v2) | (is.na(v1) & is.na(v2))same[is.na(same)] <- FALSEreturn(same)
}
应用该函数比较布尔向量
compareNA(df$a, df$b)
#> [1] TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUEdata.frame(df, isSame = compareNA(df$a,df$b))
#> a b isSame
#> 1 TRUE TRUE TRUE
#> 2 TRUE FALSE FALSE
#> 3 TRUE NA FALSE
#> 4 FALSE TRUE FALSE
#> 5 FALSE FALSE TRUE
#> 6 FALSE NA FALSE
#> 7 NA TRUE FALSE
#> 8 NA FALSE FALSE
#> 9 NA NA TRUE
应用该函数比较因子
即使因子的水平顺序不同
# 先创建两列因子
df1 <- data.frame(a = factor(c('x','x','x','y','y','y', NA, NA, NA)),b = factor(c('x','y', NA,'x','y', NA,'x','y', NA)))# 比较因子
data.frame(df1, isSame = compareNA(df1$a, df1$b))
#> a b isSame
#> 1 x x TRUE
#> 2 x y FALSE
#> 3 x <NA> FALSE
#> 4 y x FALSE
#> 5 y y TRUE
#> 6 y <NA> FALSE
#> 7 <NA> x FALSE
#> 8 <NA> y FALSE
#> 9 <NA> <NA> TRUE# 即便因子顺序被改变,也不影响比较结果
df1$b <- factor(df1$b, levels=c('y','x'))
data.frame(df1, isSame = compareNA(df1$a, df1$b))
#> a b isSame
#> 1 x x TRUE
#> 2 x y FALSE
#> 3 x <NA> FALSE
#> 4 y x FALSE
#> 5 y y TRUE
#> 6 y <NA> FALSE
#> 7 <NA> x FALSE
#> 8 <NA> y FALSE
#> 9 <NA> <NA> TRUE