1. 4×3 DataFrame
    2. Row id date age
    3. Int64 String String
    4. ─────┼───────────────────────────────
    5. 1 1 28-01-2018 adolescent
    6. 2 2 03-04-2019 adult
    7. 3 3 01-08-2018 infant
    8. 4 4 22-11-2020 adult

    因为日期列的类型并不正确,所以 sort 并不能正常工作:

    1. sort(wrong_types(), :date)
    1. 4×3 DataFrame
    2. Row id date age
    3. Int64 String String
    4. ─────┼───────────────────────────────
    5. 1 3 01-08-2018 infant
    6. 2 2 03-04-2019 adult
    7. 3 4 22-11-2020 adult
    8. 4 1 28-01-2018 adolescent

    为了修复此问题,可以使用在 Section 3.5.1 中提到的 Julia 标准库 Date 模块:

    1. function fix_date_column(df::DataFrame)
    2. strings2dates(dates::Vector) = Date.(dates, dateformat"dd-mm-yyyy")
    3. dates = strings2dates(df[!, :date])
    4. df[!, :date] = dates
    5. df
    6. end
    7. fix_date_column(wrong_types())
    1. 4×3 DataFrame
    2. Row id date age
    3. ─────┼───────────────────────────────
    4. 1 1 2018-01-28 adolescent
    5. 2 2 2019-04-03 adult
    6. 3 3 2018-08-01 infant
    7. 4 4 2020-11-22 adult

    现在,排序的结果与预期相符:

    1. df = fix_date_column(wrong_types())
    2. sort(df, :date)
    1. sort(wrong_types(), :age)
    1. 4×3 DataFrame
    2. Row id date age
    3. Int64 String String
    4. ─────┼───────────────────────────────
    5. 1 1 28-01-2018 adolescent
    6. 2 2 03-04-2019 adult
    7. 3 4 22-11-2020 adult
    8. 4 3 01-08-2018 infant

    这显然不正确,因为婴儿比成年人和青少年更年轻。 对于此问题和其他分类数据的解决方案是 CategoricalArrays.jl

    1. using CategoricalArrays

    可以使用 CategoricalArrays.jl 包为分类变量数据添加层级顺序:

    1. function fix_age_column(df)
    2. levels = ["infant", "adolescent", "adult"]
    3. ages = categorical(df[!, :age]; levels, ordered=true)
    4. df[!, :age] = ages
    5. df
    6. end
    7. fix_age_column(wrong_types())
    1. 4×3 DataFrame
    2. Row id date age
    3. 1 1 28-01-2018 adolescent
    4. 2 2 03-04-2019 adult
    5. 3 3 01-08-2018 infant
    6. 4 4 22-11-2020 adult
    1. df = fix_age_column(wrong_types())
    2. sort(df, :age)

    因为已经定义了一组函数,因此可以通过调用函数来定义修正后的数据:

    1. function correct_types()
    2. df = wrong_types()
    3. df = fix_date_column(df)
    4. df = fix_age_column(df)
    5. end
    6. correct_types()
    1. 4×3 DataFrame
    2. Row id date age
    3. Int64 Date Cat
    4. ─────┼───────────────────────────────
    5. 1 1 2018-01-28 adolescent
    6. 2 2 2019-04-03 adult
    7. 3 3 2018-08-01 infant
    8. 4 4 2020-11-22 adult

    数据中的年龄是有序的 (ordered=true),因此可以正确比较年龄类别:

    1. df = correct_types()
    2. a = df[1, :age]
    3. b = df[2, :age]
    4. a < b
    1. true

    如果元素类型为字符串,这将产生错误的比较:

      1. false