Skip to content

R - CSV 文件

R 在数据分析方面极其强大,而从外部文件导入数据通常是第一步。逗号分隔值(CSV)文件是存储表格数据最常见的格式之一。本章将指导您如何使用 Tidyverse 在 R 中以现代化、高效且可重现的方式读取和写入 CSV 文件。

最佳实践:使用 RStudio 项目实现可重现的工作流

Section titled “最佳实践:使用 RStudio 项目实现可重现的工作流”

在读取任何文件之前,正确设置我们的项目至关重要。初学者一个常见但有问题的做法是使用 setwd() 来更改工作目录。这会使您的代码变得脆弱,并且难以在其他环境中运行。

现代的最佳实践是使用 RStudio 项目。RStudio 项目(.Rproj 文件)将您的工作锚定到特定目录。当您打开一个项目时,工作目录会自动设置为项目的根文件夹。这确保了文件路径如 "data/input.csv" 始终有效,无论项目文件夹位于您计算机的哪个位置。

如何开始:

  1. 在 RStudio 中,依次点击 File > New Project... > New Directory > New Project。
  2. 给您的项目命名(例如,r-data-analysis)。
  3. 在您的项目内部创建一个名为 data 的子文件夹,并将您的 CSV 文件保存到其中。

首先,请确保您拥有必要的工具。我们将使用 tidyverse 中的包,这是一个为数据科学设计的 R 包集合。如果您尚未安装,请在您的 R 控制台中运行以下命令:

install.packages("tidyverse")

接下来,在您的项目 data 子文件夹中创建一个名为 input.csv 的 CSV 文件,内容如下。您可以使用纯文本编辑器或电子表格程序。

id,name,salary,start_date,dept
1,Rick,623.3,2012-01-01,IT
2,Dan,515.2,2013-09-23,Operations
3,Michelle,611,2014-11-15,IT
4,Ryan,729,2014-05-11,HR
,Gary,843.25,2015-03-27,Finance
6,Nina,578,2013-05-21,IT
7,Simon,632.8,2013-07-30,Operations
8,Guru,722.5,2014-06-17,Finance

readr 包(tidyverse 的一部分)提供了 read_csv(),这是一个快速且现代的读取 CSV 文件的函数。它通常优于基础 R 的 read.csv(),因为它更快,提供更多信息输出,并创建 tibbles 而不是标准数据框。

# 加载 tidyverse 库,其中包含 readr 和 dplyr
library(tidyverse)
# 定义相对于项目根目录的文件路径
file_path <- "data/input.csv"
# 将 CSV 文件读取为 tibble
employee_data <- read_csv(file_path)
# 打印 tibble 以查看其内容和结构
print(employee_data)

当您运行此代码时,read_csv() 将打印列规范的摘要,这对于调试非常有帮助。

Rows: 8 Columns: 5
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
dbl (2): id, salary
chr (2): name, dept
dte (1): start_date
# A tibble: 8 × 5
id name salary start_date dept
<dbl> <chr> <dbl> <date> <chr>
1 1 Rick 623. 2012-01-01 IT
2 2 Dan 515. 2013-09-23 Operations
3 3 Michelle 611 2014-11-15 IT
4 4 Ryan 729 2014-05-11 HR
5 NA Gary 843. 2015-03-27 Finance
6 6 Nina 578 2013-05-21 IT
7 7 Simon 633. 2013-07-30 Operations
8 8 Guru 722. 2014-06-17 Finance

一旦您的数据加载到 tibble 中,您就可以使用 dplyr 包(同样是 tidyverse 的一部分)来操作和分析它。dplyr 使用一套直观的“动词”和管道操作符 %>% 来创建高度可读的数据分析管道。

我们使用 summarize() 来计算汇总统计量。处理潜在的缺失值 (NA) 时使用 na.rm = TRUE 是一个很好的习惯。

# 查找最高薪资,忽略任何 NA 值
max_salary <- employee_data %>%
summarize(max_sal = max(salary, na.rm = TRUE))
print(max_salary)

结果:

# A tibble: 1 × 1
max_sal
<dbl>
1 843.

我们使用 filter() 根据条件筛选行。

# 筛选数据以找到薪资最高的员工
top_earner <- employee_data %>%
filter(salary == max(salary, na.rm = TRUE))
print(top_earner)

结果:

# A tibble: 1 × 5
id name salary start_date dept
<dbl> <chr> <dbl> <date> <chr>
1 NA Gary 843. 2015-03-27 Finance
# 筛选 'IT' 部门的员工
it_employees <- employee_data %>%
filter(dept == "IT")
print(it_employees)

结果:

# A tibble: 3 × 5
id name salary start_date dept
<dbl> <chr> <dbl> <date> <chr>
1 1 Rick 623. 2012-01-01 IT
2 3 Michelle 611 2014-11-15 IT
3 6 Nina 578 2013-05-21 IT

您可以在单个 filter() 调用中组合多个条件。

# 组合多个筛选条件(逗号表示 AND)
info <- employee_data %>%
filter(dept == "IT", salary > 620)
print(info)

结果:

# A tibble: 1 × 5
id name salary start_date dept
<dbl> <chr> <dbl> <date> <chr>
1 1 Rick 623. 2012-01-01 IT

获取 2014 年 1 月 1 日或之后入职的员工

Section titled “获取 2014 年 1 月 1 日或之后入职的员工”

因为 read_csv 正确地将 start_date 列识别为日期类型,我们可以直接对其进行筛选。

# 根据日期列进行筛选
recent_hires <- employee_data %>%
filter(start_date >= as.Date("2014-01-01"))
print(recent_hires)

结果:

# A tibble: 4 × 5
id name salary start_date dept
<dbl> <chr> <dbl> <date> <chr>
1 3 Michelle 611 2014-11-15 IT
2 4 Ryan 729 2014-05-11 HR
3 NA Gary 843. 2015-03-27 Finance
4 8 Guru 722. 2014-06-17 Finance

在筛选或转换数据之后,您通常会希望保存结果。readr::write_csv() 是 read_csv() 的完美对应函数。它能高效地将数据框或 tibble 写入 CSV 文件。

write_csv() 的一个关键优点是它默认不写入行名,这避免了输出文件中出现一个额外的、无名列的常见问题。

# 使用上一步中的 'recent_hires' tibble...
# 定义输出文件路径
output_path <- "data/output.csv"
# 将筛选后的数据写入新的 CSV 文件
write_csv(recent_hires, output_path)
# 为了验证,您可以将新文件重新读入并打印
new_data <- read_csv(output_path)
print(new_data)

生成的 output.csv 文件将是干净且格式正确的,仅包含您想要保存的数据。

# A tibble: 4 × 5
id name salary start_date dept
<dbl> <chr> <dbl> <date> <chr>
1 3 Michelle 611 2014-11-15 IT
2 4 Ryan 729 2014-05-11 HR
3 NA Gary 843. 2015-03-27 Finance
4 8 Guru 722. 2014-06-17 Finance