## 4.3 Filter 和 Subset

DataFrames.jl 较早地添加了 filter 函数, 它更强大且与 Julia Base 库的语法保持一致，因此我们先讨论 filtersubset 是较新的函数，但它通常更简便。

### 4.3.1 Filter

grades_2020()
Sally 1.0
Bob 5.0
Alice 8.5
Hank 4.0

equals_alice(name::String) = name == "Alice"
equals_alice("Bob")
false
equals_alice("Alice")
true

filter(:name => equals_alice, grades_2020())
Alice 8.5

filter(equals_alice, ["Alice", "Bob", "Dave"])
["Alice"]

filter(n -> n == "Alice", ["Alice", "Bob", "Dave"])
["Alice"]

filter(:name => n -> n == "Alice", grades_2020())
Alice 8.5

filter(:name => ==("Alice"), grades_2020())
Alice 8.5

### 4.3.2 Subset

subset 函数的加入使得处理 missing 值 (Section 4.5) 更加容易。 与 filter 相反， subset 对整列进行操作，而不是整行或者单个值。 如果想使用之前的函数，可以将其包装在 ByRow 里：

subset(grades_2020(), :name => ByRow(equals_alice))
Alice 8.5

NOTE: subset 所属的大多数原生 DataFrames.jl 函数都保持着一致的函数签名，即 DataFrame 作为第一个参数

filter 一样，可以在 subset 中使用匿名函数：

subset(grades_2020(), :name => ByRow(name -> name == "Alice"))
Alice 8.5

subset(grades_2020(), :name => ByRow(==("Alice")))
Alice 8.5

function salaries()
names = ["John", "Hank", "Karen", "Zed"]
salary = [1_900, 2_800, 2_800, missing]
DataFrame(; names, salary)
end
salaries()
Table 6: Salaries.
names salary
John 1900
Hank 2800
Karen 2800
Zed missing

filter(:salary => >(2_000), salaries())
TypeError: non-boolean (Missing) used in boolean context
Stacktrace:
[1] (::DataFrames.var"#97#98"{Base.Fix2{typeof(>), Int64}})(x::Missing)
@ DataFrames ~/.julia/packages/DataFrames/6xBiG/src/abstractdataframe/abstractdataframe.jl:1110
...

subset 同样会失败，但幸运的是，报错指出一则简单的解决方案：

subset(salaries(), :salary => ByRow(>(2_000)))
ArgumentError: missing was returned in condition number 1 but only true or false are allowed; pass skipmissing=true to skip missing values
Stacktrace:
[1] _and(x::Missing)
@ DataFrames ~/.julia/packages/DataFrames/6xBiG/src/abstractdataframe/subset.jl:11
...

subset(salaries(), :salary => ByRow(>(2_000)); skipmissing=true)
names salary
Hank 2800
Karen 2800

1. 15. 这来自于 Bogumił Kamiński （DataFrames.jl 的首席开发者和维护者） 在 Discourse (https://discourse.julialang.org/t/pull-dataframes-columns-to-the-front/60327/5) 论坛上的发言。↩︎

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