4.1 加载和保存文件

仅在 Julia 程序中使用数据非常有局限性,通常还需要能够加载或保存数据。 因此,本节主要讨论如何存储文件到硬盘和从硬盘读取文件。 我们重点关注 CSV 和 Excel 这两类最常见的数据文件格式,分别参见 Section 4.1.1 和 Section 4.1.2

4.1.1 CSV

Comma-separated-values (CSV) 文件是非常有效的表格存储方式。 CSV 文件相比其他数据存储文件有两点优势。首先,正如名称所指示的那样,它使用逗号,来分隔存储值。此首字母缩写词也被用作文件扩展名。因此,请确保使用“.csv”扩展名(例如“myfile.csv”)保存文件。为了演示 CSV 文件的结构,安装 CSV.jl 包:

  1. julia> ]
  2. pkg> add CSV

并且通过以下方式导入:

  1. using CSV

现在可使用之前的数据:

  1. grades_2020()
namegrade_2020
Sally1.0
Bob5.0
Alice8.5
Hank4.0

并在写入后从文件中读取:

  1. function write_grades_csv()
  2. path = "grades.csv"
  3. CSV.write(path, grades_2020())
  4. end
  1. path = write_grades_csv()
  2. read(path, String)
  1. name,grade_2020
  2. Sally,1.0
  3. Bob,5.0
  4. Alice,8.5
  5. Hank,4.0

上文还能看到 CSV 数据格式的第二个好处:可以使用简单的文本编辑器读取数据。 这与许多需要专有软件的其他数据格式不同,例如 Excel。

这很有效,但是如果我们的数据 包含逗号 , 作为值怎么办? 如果我们天真地用逗号写入数据,那么文件将很难转换回表格。 幸运的是,CSV.jl 会自动处理此问题。 考虑以下带逗号,的数据:

  1. function grades_with_commas()
  2. df = grades_2020()
  3. df[3, :name] = "Alice,"
  4. df
  5. end
  6. grades_with_commas()
Table 5: Grades with commas.
namegrade_2020
Sally1.0
Bob5.0
Alice,8.5
Hank4.0

如果写入文件,将得到:

  1. function write_comma_csv()
  2. path = "grades-commas.csv"
  3. CSV.write(path, grades_with_commas())
  4. end
  5. path = write_comma_csv()
  6. read(path, String)
  1. name,grade_2020
  2. Sally,1.0
  3. Bob,5.0
  4. "Alice,",8.5
  5. Hank,4.0

因此,CSV.jl 在包含逗号的值周围添加引号 "。 解决此问题的另一种常见方法是将数据写入 tab-separated values (TSV) 文件格式。 该格式假设数据不包含制表符,这一点在大多数情况下是成立的。

另请注意,也可以使用简单的文本编辑器读取 TSV 文件,这些文件使用“.tsv”扩展名。

  1. function write_comma_tsv()
  2. path = "grades-comma.tsv"
  3. CSV.write(path, grades_with_commas(); delim='\t')
  4. end
  5. read(write_comma_tsv(), String)
  1. name grade_2020
  2. Sally 1.0
  3. Bob 5.0
  4. Alice, 8.5
  5. Hank 4.0

像 CSV 和 TSV 这样的文本文件格式还可以使用其他分割符,例如分号“;”,空格“ ”,甚至是像“π”这样不寻常的字符。

  1. function write_space_separated()
  2. path = "grades-space-separated.csv"
  3. CSV.write(path, grades_2020(); delim=' ')
  4. end
  5. read(write_space_separated(), String)
  1. name grade_2020
  2. Sally 1.0
  3. Bob 5.0
  4. Alice 8.5
  5. Hank 4.0

按照惯例,最好还是为文件指定特殊的分隔符,例如“;”,“.csv”扩展名。

使用 CSV.jl 加载 CSV 文件的方式与此类似。 您可以使用 CSV.read 并指定您想要的输出格式。 这里指定为DataFrame

  1. path = write_grades_csv()
  2. CSV.read(path, DataFrame)
namegrade_2020
Sally1.0
Bob5.0
Alice8.5
Hank4.0

方便地,CSV.jl将自动推断列类型:

  1. path = write_grades_csv()
  2. df = CSV.read(path, DataFrame)
  1. 4×2 DataFrame
  2. Row name grade_2020
  3. String7 Float64
  4. ─────┼─────────────────────
  5. 1 Sally 1.0
  6. 2 Bob 5.0
  7. 3 Alice 8.5
  8. 4 Hank 4.0

它甚至适用于更复杂的数据:

  1. my_data = """
  2. a,b,c,d,e
  3. Kim,2018-02-03,3,4.0,2018-02-03T10:00
  4. """
  5. path = "my_data.csv"
  6. write(path, my_data)
  7. df = CSV.read(path, DataFrame)
  1. 1×5 DataFrame
  2. Row a b c d e
  3. String3 Date Int64 Float64 DateTime
  4. ─────┼──────────────────────────────────────────────────────────
  5. 1 Kim 2018-02-03 3 4.0 2018-02-03T10:00:00

这些CSV基础应该涵盖大多数用例。 关于更多信息,请参阅CSV.jl 文档尤其是CSV.File 构建 docstring

4.1.2 Excel

多个 Julia 包可以读取 Excel 文件。 本节将只讨论 XLSX.jl,因为它是 Julia 生态系统中处理 Excel 数据的最积极维护的包。 另外一个优点是,XLSX.jl 是用纯 Julia 编写的,这使得可以轻松地检查和理解指令背后发生的事情。

加载 XLSX.jl 的方式是

  1. using XLSX:
  2. eachtablerow,
  3. readxlsx,
  4. writetable

为了写入文件,我们为数据和列名定义一个辅助函数:

  1. function write_xlsx(name, df::DataFrame)
  2. path = "$name.xlsx"
  3. data = collect(eachcol(df))
  4. cols = names(df)
  5. writetable(path, data, cols)
  6. end

现在,可以轻松地将成绩写入 Excel 文件:

  1. function write_grades_xlsx()
  2. path = "grades"
  3. write_xlsx(path, grades_2020())
  4. "$path.xlsx"
  5. end

当成绩被读取回来时,我们将看到 XLSX.jl 将数据放在 XLSXFile 类型中,并且可以像访问 Dict 一样访问所需的 sheet

  1. path = write_grades_xlsx()
  2. xf = readxlsx(path)
  1. XLSXFile("grades.xlsx") containing 1 Worksheet
  2. sheetname size range
  3. -------------------------------------------------
  4. Sheet1 5x2 A1:B5
  1. xf = readxlsx(write_grades_xlsx())
  2. sheet = xf["Sheet1"]
  3. eachtablerow(sheet) |> DataFrame
namegrade_2020
Sally1.0
Bob5.0
Alice8.5
Hank4.0

请注意,本节只介绍了XLSX.jl的基础知识,但它还提供了更强大的用法和自定义功能。 有关更多信息和选项,请参阅XLSX.jl 文档.

CC BY-NC-SA 4.0 Jose Storopoli, Rik Huijzer, Lazaro Alonso, 刘贵欣 (中文翻译), 田俊 (中文审校)