Выражение:
DataFrame(x=1).x .> 1
Выполняет следующие действия:
- Создает
DataFrame
- Извлекает из него столбец
x
- Сравнивает все элементы этого столбца с
1
, используя векторизованную операцию .>
(вещание на языке Юлии)
Фактически вы получаете следующий массив из одного элемента:
julia> DataFrame(x=1).x .> 1
1-element BitArray{1}:
false
В отличие от R, Юлия различает векторы и скаляры, поэтому это не то же самое, что просто написать false
. Более того, оператор if
ожидает скаляр, а не вектор, поэтому что-то вроде этого работает:
if 2 > 1
println("2 is greater than 1")
end
но не как то так:
if DataFrame(x=2).x .> 1
println("success!")
end
Однако, например, это будет работать:
if (DataFrame(x=2).x .> 1)[1]
println("success!")
end
при извлечении первого (и только в этом случае) элемента из массива.
Обратите внимание, что в R
, если вы передали условному выражению более одного элемента вектора, вы получите следующее предупреждение:
> if (c(T,F)) {
+ print("aaa") } else {print("bbb")}
[1] "aaa"
Warning message:
In
the condition has length > 1 and only the first element will be used
Просто Джулия при проверке типов в этом случае строже, чем R. В R у вас нет различий между скалярами и векторами, но в Юлии у вас есть.
EDIT:
length(df)
возвращает количество столбцов из DataFrame
(не количество строк). Если вы выходите из R
, вам будет легче запомнить функции nrow
и ncol
.
Теперь по вашему вопросу вы можете написать:
for i in 1:nrow(df)
if df.x[i] > 3
df.y[i] = df.x[i] + 1
end
end
или
bigx = df.x .> 3
df.y[bigx] = df.x[bigx] .+ 1
или
df.y .= ifelse.(df.x .> 3, df.x .+ 1, df.y)
или использование DataFramesMeta
для сокращения записи:
using DataFramesMeta
@with df begin
df.y .= ifelse.(:x .> 3, :x .+ 1, :y)
end
или
using DataFramesMeta
@byrow! df begin
if :x > 3
:y = :x + 1
end
end