在 Section 4.4 中, 我们使用 select
函数选择一列或多列源数据, 并传入一个或多个目标列 source => target
。 同样也有例子帮助回忆: select(df, :name => :people_names)
。
本节将讨论如何 变换 变量,即如何 更改数据。 DataFrames.jl
中对应的语法是 source => transformation => target
。
与之前一样,使用 grades_2020
数据集:
假设想要 grades_2020
中的所有成绩加 1。 首先,需要定义一个接收向量数据并使所有元素加 1 的函数。 然后使用 DataFrames.jl
中的 transform
函数。与其他原生 DataFrames.jl
函数一样,按照其语法,它接收 DataFrame
作为第一个参数:
transform(grades_2020(), :grade_2020 => plus_one)
name | grade_2020 | grade_2020_plus_one |
---|---|---|
Sally | 1.0 | 2.0 |
Bob | 5.0 | 6.0 |
Alice | 8.5 | 9.5 |
Hank | 4.0 | 5.0 |
如之前所说, DataFrames.jl
总是支持 source => transformation => target
这样的短语法。 所以,如果想在输出中保留 target
列的命名,操作如下:
transform(grades_2020(), :grade_2020 => plus_one => :grade_2020)
也可以使用关键字参数 renamecols=false
:
name | grade_2020 |
---|---|
Sally | 2.0 |
Bob | 6.0 |
Alice | 9.5 |
Hank | 5.0 |
还可以使用 select
实现相同的转换,具体如下:
select(grades_2020(), :, :grade_2020 => plus_one => :grade_2020)
其中 :
表明 “选择所有列” ,正如在 Section 讨论的那样。 另外,还可以使用 Julia 广播更改 grade_2020
列,即直接访问 :
df.grade_2020 = plus_one.(df.grade_2020)
df
name | grade_2020 |
---|---|
Sally | 2.0 |
Bob | 6.0 |
Alice | 9.5 |
Hank | 5.0 |
为了展示如何同时更改两列, 我们使用 Section 中的左合并数据:
结合此数据集,我们增加一列来判断每位同学是否都有一门课的成绩大于 5.5:
pass(A, B) = [5.5 < a || 5.5 < b for (a, b) in zip(A, B)]
transform(leftjoined, [:grade_2020, :grade_2021] => pass; renamecols=false)
name | grade_2020 | grade_2021 | grade_2020_grade_2021 |
---|---|---|---|
Sally | 1.0 | 9.5 | true |
Hank | 4.0 | 6.0 | true |
Bob | 5.0 | missing | missing |
Alice | 8.5 | missing | true |
可以清理下结果,并将上述逻辑整合到一个函数中,然后最终得到符合标准学生的名单:
function only_pass()
pass(A, B) = [5.5 < a || 5.5 < b for (a, b) in zip(A, B)]
leftjoined = transform(leftjoined, [:grade_2020, :grade_2021] => pass => :pass)
passed = subset(leftjoined, :pass; skipmissing=true)
return passed.name
end