R语言数据分析(二)
前言
数据分析的整个流程从数据的导入开始,有多种形式的数据都可以分别导入到R中进行分析。这次我们就从简单的文本数据开始。
一、纯文本数据简单导入
首先简单介绍纯文本数据导入的基本方法。在我们先前的R语言入门与实践系列,已经学习过使用read.csv
等进行数据导入。在tidyverse
包中的readr
包也提供了导入函数。
library(tidyverse)
1.1 csv文件
csv,是常见的纯文本数据格式,它是逗号分隔值的缩写。我们可以使用read_csv()
将文件读入R。第一个参数为文件的地址。
另外,该函数还提供了NA的识别参数,可以将不同形式的数据识别为NA。比如:
# 通过na参数将一些字符识别为NA值
data <- read_csv("data/data1.csv", na = c("N/A", "?", ""))
#> Rows: 5 Columns: 3
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> chr (1): City
#> dbl (2): ID, Now AQI
#>
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
data
#> # A tibble: 5 × 3
#> ID City `Now AQI`
#> <dbl> <chr> <dbl>
#> 1 1 Zhengzhou 79
#> 2 2 Wuxi 134
#> 3 3 Shanghai 142
#> 4 4 Beijing 60
#> 5 5 Hefei 92
注意这个会将文件读取为tibble表格形式,这是tidyverse具有的数据形式,在读取列名时如果遇到其中带有空格的列名,列名显示会带有反引号`
。要引用这些变量时需要使用反引号将其括起来。
data |>
rename(
now_AQI = `Now AQI`
)
#> # A tibble: 5 × 3
#> ID City now_AQI
#> <dbl> <chr> <dbl>
#> 1 1 Zhengzhou 79
#> 2 2 Wuxi 134
#> 3 3 Shanghai 142
#> 4 4 Beijing 60
#> 5 5 Hefei 92
除此之外,还有一种方法就是使用janitor::clean_names()
来一键更改格式:
data |> janitor:: clean_names()
#> # A tibble: 5 × 3
#> id city now_aqi
#> <dbl> <chr> <dbl>
#> 1 1 Zhengzhou 79
#> 2 2 Wuxi 134
#> 3 3 Shanghai 142
#> 4 4 Beijing 60
#> 5 5 Hefei 92
1.2 文本字符串
read_csv()
还可用于读取文本字符串格,比如:
read_csv(
"a,b,c
1,2,3
4,5,6"
)
#> Rows: 2 Columns: 3
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> dbl (3): a, b, c
#>
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#> # A tibble: 2 × 3
#> a b c
#> <dbl> <dbl> <dbl>
#> 1 1 2 3
#> 2 4 5 6
它会将第一行作为列名,可以使用skip = n
来跳过前n行,或者使用comment = "#"
跳过开头为“#”字符的行。可以使用col_nemes = F
来忽略第一行作为列名,也可以使用col_names = c("colname1", "colname2")
来添加新的列名。
1.3 其他文件类型
下面介绍几个其他文件类型的读取函数:
-
read_csv2()
读取;
分隔的文件 -
read_tsv()
读取tsv文件 -
read_delim()
读取带任意分隔符的文件,如未指定则会猜测分隔符 -
read_fwf()
读取固定宽度文件,fwf_widths()
指定宽度,fwf_positions()
指定位置 -
read_table()
读取空格分隔的文件 -
read_log()
读取Apche格式的log文件 -
…
具体用法可以通过查看函数帮助文件来自行学习。
1.4 列类型控制
首先readr
在读取数据的时候,会对每一列读取前1000行来分析其中数值的类型(忽略其中的NA值):
-
仅含
F
、T
、FALSE
、TRUE
的值(大小写均可),判断类型为逻辑型 -
仅含数字的,判断类型为数值型
-
符合ISO8601标准的,判断为时间类型
-
否则,判断为字符串类型
有些类型判断错误是由于缺失值导致的,比如下面的csv文件:
example_csv <- "
x
1
.
2
3
5"
由于.
的存在会让它在读取时被认定为字符串属性。我们将它设置为缺失值即可:
df <- read_csv(example_csv)
#> Rows: 5 Columns: 1
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> chr (1): x
#>
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df
#> # A tibble: 5 × 1
#> x
#> <chr>
#> 1 1
#> 2 .
#> 3 2
#> 4 3
#> 5 5
df <- read_csv(example_csv, na = ".")
#> Rows: 5 Columns: 1
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> dbl (1): x
#>
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df
#> # A tibble: 5 × 1
#> x
#> <dbl>
#> 1 1
#> 2 NA
#> 3 2
#> 4 3
#> 5 5
但是如果数据很多,无法直观看到缺失值的符号呢?这个时候可以告诉readr,x列是一个数字列,然后查看失败位置。可以使用col_types
参数来执行操作,它采用命名列表,名称与csv文件中列名称匹配:
df <- read_csv(
example_csv,
col_types = list(x = col_double())
)
#> Warning: One or more parsing issues, call `problems()` on your data frame for details,
#> e.g.:
#> dat <- vroom(...)
#> problems(dat)
看到警告信息后,我们可以进一步查看位置:
problems(df)
#> # A tibble: 1 × 5
#> row col expected actual file
#> <int> <int> <chr> <chr> <chr>
#> 1 3 1 a double . C:/Users/lmy/AppData/Local/Temp/RtmpeYJgZv/file8a…
由此我们直到第三行第一列存在问题,出现了.
符号。
那么像这样的列类型还有几种:
-
col_logical()
、col_double()
、col_integer()
、col_character()
、col_factor()
、col_data()
、col_datatime()
、col_number()
分别代表其类型 -
col_skip()
会跳过一列,因此它不会包含在结果中,如果您有一个大型CSV文件并且只想使用某些列,这对于加快读取数据的速度很有用。
另外,还可以使用cols
替代list
通过.default
来指定默认列指定类型:
another_csv <- "
x,y,z
1,2,3"
read_csv(
another_csv,
col_types = cols(.default = col_character())
)
#> # A tibble: 1 × 3
#> x y z
#> <chr> <chr> <chr>
#> 1 1 2 3
由此可见,每列的值都已经是character了。
1.5 多个文件读取
多个文件读取方法如下:
m_files <- c("data/data1.csv", "data/data2.csv")
read_csv(m_files, id = "file")
#> Rows: 6 Columns: 4
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: ","
#> chr (1): City
#> dbl (2): ID, Now AQI
#>
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#> # A tibble: 6 × 4
#> file ID City `Now AQI`
#> <chr> <dbl> <chr> <dbl>
#> 1 data/data1.csv 1 Zhengzhou 79
#> 2 data/data1.csv 2 Wuxi 134
#> 3 data/data1.csv 3 Shanghai 142
#> 4 data/data1.csv 4 Beijing 60
#> 5 data/data1.csv 5 Hefei 92
#> 6 data/data2.csv 1 <NA> NA
如果您要读入许多文件,则将它们的名称写为列表可能会很麻烦。但是,您可以使用基本 list.files() 函数通过正则表达式匹配文件名来查找文件。
m_files <- list.files("data", pattern = "\\.csv$")
m_files
#> [1] "data1.csv" "data2.csv"
1.6 输出数据
可以使用函数write_csv()
等通过write_csv(data, "filename")
进行。
另外,可以使用write_rds()
以RDS文件格式存储R表格,保存了R表的特征,在读取时可以使用read_rds()
进行。
1.7 手动输入数据
需要手动输入数据时,可以有以下两种形式:
tibble(
x = c(1, 2, 3),
y = c("a", "b", "c"),
z = c(0.01, 0.02, 0.03)
)
#> # A tibble: 3 × 3
#> x y z
#> <dbl> <chr> <dbl>
#> 1 1 a 0.01
#> 2 2 b 0.02
#> 3 3 c 0.03
# 另一种
tribble(
~x, ~y, ~z,
1, "a", 0.01,
2, "b", 0.02,
3, "c", 0.03
)
#> # A tibble: 3 × 3
#> x y z
#> <dbl> <chr> <dbl>
#> 1 1 a 0.01
#> 2 2 b 0.02
#> 3 3 c 0.03
总结
通过本章学习,我们学到了最简单的一种数据的导入形式,即文本数据,最常见的是csv格式的数据。读取为tibble表格后会自动分析每列数据类型。我们可以通过数据检查来找到其中NA值的表示形式,从而避免类型的错误识别。最后学习了多个文件读取进一个tibble的方法,也学习了数据的输出方式。后续我们会继续学习其他更多格式的数据导入方式。
持续更新中…