「R语言刷题笔记」数据类型篇 - 从tidyr和dplyr入手

R语言到底可以用来做什么?

在生物信息学领域,大数据、机器学习等方向,和Python一比,我感觉已经相形见绌,

所以为什么还要学习R语言?

1)ggplot2的绘图体系非常完美

2)R base能够完成我日常小数据的分析

有很多人说,tidyverse给了R二次生命,但是在我看来它的编程思维,稍显奇怪,不太能够适应,

但是我属于一个钻牛角尖的人,既然学了,而且R我也没有完全丢掉,也是有一定必要学习一些重获新生的R语言。

因此这篇文章就是针对我在最近的R语言刷题中的总结。

数据读入 / 写出

从R base的角度看问题

read.table()
read.csv()
write.table()
write.csv()

readr的角度看问题

read_csv()
read_delim()
read_table()
write_delim(df, 'filename.csv')
write_csv(df, 'filename.csv')
write_excel_csv(df, 'filename.csv')
write_tsv(df, 'filename.csv')

data.frame

从R base的角度看问题

如何随心所欲的操作data.frame

使用data.frame()创建数据库,

1)给定colname,再给定该变量对应的element(一般是vector格式),即

colname=c(elements)

2)依此类推,增添每一列

# 1. 数据框的创建
df <- data.frame(
  "grammer" = c("Python","C","Java","GO",NA,"SQL","PHP","Python"),
  "score" = c(1,2,NA,4,5,6,7,10)
)

tidyr的角度看问题

library(tidyr)
df <- tibble(
  "grammer" = c("Python","C","Java","GO",NA,"SQL","PHP","Python"),
  "score" = c(1,2,NA,4,5,6,7,10)
)
# # A tibble: 8 x 2
#   grammer score
#   <chr>   <dbl>
# 1 Python      1
# 2 C           2
# 3 Java       NA
# 4 GO          4
# 5 NA          5
# 6 SQL         6
# 7 PHP         7
# 8 Python     10

dplyr的衔接

dplyr提供了一系列用C++重新编写过的函数,能够加快我们处理数据的速度。

主要包含的函数如下,

select()
filter()
mutate()
group_by()
arrange()

1)数据框列名的重新命名:names(), colnames(), rename()

R base对列名进行修改的话,使用如下格式,

# R base
names(df)[2] <- c('popularity')

# dplyr
df <- df %>% rename(popularity = score)

2)数据过滤:which(), filter()

# R base
df[which(df$popularity > 3), ]

# dplyr
df %>%
  filter(popularity > 3)

# 按照范围也是一样的,
df %>%
  filter(popularity > 3 & popularity <7)

3)选择某一列数据:$, select()

# R base
df$popularity

# dplyr
df <- df %>%
    select(popularity, everything())

Note:tidyverse::everything()的作用,为选择数据框中的所有变量。

select()函数一起使用,可以改变数据框中变量的排列顺序(e.g. 将变量A从变量B后移动到变量B前),以iris数据集为例,

select(iris, everything())
#  A tibble: 150 x 5
#    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#           <dbl>       <dbl>        <dbl>       <dbl> <fct>  
#  1          5.1         3.5          1.4         0.2 setosa
select(iris, Species, everything())
# # A tibble: 150 x 5
#    Species Sepal.Length Sepal.Width Petal.Length Petal.Width
#    <fct>          <dbl>       <dbl>        <dbl>       <dbl>
#  1 setosa           5.1         3.5          1.4         0.2

可以看到Species被提前了。

4)将一行/多行数据添加到数据框中:rbind()

row <- data.frame(
  "grammer" = c("Perl"),
  "popularity" = c(6.6)
)
df <- rbind(df, row)

5)分组:aggregate(), group_by

  • R base:aggregate()
  • dplyr:group_by + summarise
# R base
# 使用aggregate对df进行分组计算
library(flipAPI)
data = DownloadXLSX("https://wiki.q-researchsoftware.com/images/1/1b/Aggregation_data.xlsx", want.row.names = FALSE, want.data.frame = TRUE)
data.agg = aggregate(df,
                by = list(data$Role),
                FUN = mean)

# dplyr
# 使用group_by()分组,并进行相关计算
library(readr)
df <- read_csv('pandas120.csv')
df %>%
  group_by(education) %>%    # 设置用于分组的变量,此处为education
  summarise(mean = mean(salary))

6)构建新的一列变量:mutate()

# R base
# 使用cbind()函数

# dplyr
df <- df %>%
  mutate(test = paste0(df$education, df$createTime))

Note:paste0,先将变量转换为字符类型

7)将某一列的设置为索引:rownames(), column_to_rownames()

# R base
rownames(df) <- df$createTime

# dplyr
# 使用column_to_rownames,该函数将某一列设置为行名后得到
df %>%
  tibble::column_to_rownames('createTime')

8)数据排序

# R base
# sort(): 返回的是排序后的结果
# order()
df <- df[order(df$popularity), ]

# dplyr
# 使用arrange()
df <- df %>%
  arrange(popularity)
df <- df %>%
  arrange(desc(popularity))

9)数据的总结:summary(), summarize()

data.frame有关的实例

1)填补NA

1)使用R包Hmisc中的impute()函数
2)使用impute函数的一般模式,一为输入的向量,二为如何填充NA值所定义的FUN

Note:下列代码中的unlist,只是为了安全作用

library(Hmisc)
index <- which(is.na(df$popularity))
df$popularity <- impute(df$popularity,
                       (unlist(df[index-1, 2] +
                               df[index+1, 2]))/2)

2)将宽数据转换为长数据

使用tidyr中的pivot_longer()函数,

一般的使用模式如下,

pivot_longer(data, 
             cols, names_to = "name",  # cols,定义一个vector用于选择df中的列并进行合并
             values_to = "value",      # 每一行对应的元素
             values_drop_na = FALSE)

举个例子,

library(tidyr)
df %>%
  select(日期,`开盘价(元)`,`收盘价(元)`) %>%
  pivot_longer(c(`开盘价(元)`,`收盘价(元)`),
               names_to='type',values_to='price') %>%
  ggplot(aes(日期,price,color=type)) +
  geom_line(size=1.2) +
  scale_color_manual(values=c('steelblue','orange')) +
  theme_bw() +
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    legend.title = element_blank(),
    legend.position = c(0.86, 0.9)
 )

3)读入数据的测试

假设现在有一个非常大的数据集,但是可以用read.csv等函数进行读入,然后后续用到的数据实际上只占了df的2列,

1)如何找到这两列?

2)如何在后续的分析中只读取到这两列?

res <- read.csv('数据1.csv',encoding = 'GBK',nrows = 3)  # 测试读入3行数据

# 获取每一列的数据类型(e.g. integer、character)
classes <- sapply(res, class)
classes[-match(c('positionName','salary'), names(classes))] <- 
	rep('NULL', length(classes) - 2)  # 保留只想要选择的列

df <- read.csv('数据1.csv', encoding = 'GBK', nrows = 10,
               colClasses = classes) # 使用"colClasses="指定列

代码的解读,

1)测试读入数据,即读取3行
2)使用sapply获取每一列的数据类型
3)去除不想要的列的数值类型,即 ->None
4)重新使用read.csv(, colClasses=),对目的数据进行读取

4)使用sapply()创建一个数据框

df1 <- sapply(20, function(n){
  replicate(n, sample(1:100, 1))
}) %>%
  as.data.frame(.) %>%
  dplyr::rename(`0` = V1)

R tips

str():查看对象每一个子对象的类型

R中有非常多的对象,比如

  • data.frame中的每一个变量都是一个子对象,
  • 列表中的每一个$,均为一个子对象
str(df)
# 'data.frame':   8 obs. of  2 variables:
#  $ grammer: Factor w/ 6 levels "C","GO","Java",..: 5 1 3 2 NA 6 4 5
#  $ score  : num  1 2 NA 4 5 6 7 10

.:既是占位符,也是通配符

.在一些情况下,可以充当占位符,比如下列代码的含义为过滤掉salary小于10000的行,且查看过滤后的数据的行数,

Note:可以类比为Shell中的-

df <- read_csv('pandas120.csv')
df %>%
  filter(salary > 10000) %>%
  dim(.) %>%
  .[1]

.的另一种含义为通配符,但是在此处不做过多赘述。

"[":索引的另一种方式

直接举例说明,

"["(c(123, 12, 3), 1)
# 123
"["(c(123, 12, 3), 2)
# 12

基于glue的格式化输出

1)使用R包glue(集合于tidyverse中),即可以直接理解为C、Pytohn中的格式化输出(e.g. sprintf

2)paste(, collapse=) -> .join()

# library(readr)
# df <- read_csv('600000.SH.csv')
library(glue)
for (i in names(df)){
  if(sum(is.na(df[,'日期'])) != 0){
    res1 <- which(is.na(df[,i]))
    res2 <- paste(res1, collapse = ',')
    print(glue('列名:"{i}", 第[{res2}]行有缺失值'))
  }
}

参考资料

[1] R语言数据处理120题

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值