使用`@ transform`转换Julia中的DataFrame

时间:2015-09-18 21:13:52

标签: iterator dataframe julia

我正在尝试使用Julia的DataFrame,我遇到了与DataFrame对象上的迭代器相关的以下问题。如果我定义一个DataFrame并在其上应用内置函数,那么DataFrame的行就会有明显的迭代:

using DataFrames, DataFramesMeta
df = DataFrame(a = [1, 2, 3], b =[6, 7, 8])

@transform(df, mt = sin(:a) .* cos(:b))

但是,如果我使用自己的函数尝试类似的模式,在这种情况下MyType的构造函数,比如说,

type MyType
    a::Float64
    b::Float64
    function MyType(in1, in2)
        new(3 * in1, 2 * in2)
    end
end

它不起作用:

@transform(df, mt = MyType(:a, :b))

给出错误消息:

LoadError: MethodError: `convert` has no method matching convert(::Type{Float64}, ::DataArrays.DataArray{Int64,1})
This may have arisen from a call to the constructor Float64(...),
since type constructors fall back to convert methods.
Closest candidates are:
  call{T}(::Type{T}, ::Any)
  convert(::Type{Float64}, !Matched::Int8)
  convert(::Type{Float64}, !Matched::Int16)
  ...
while loading In[107], in expression starting on line 1

 in ##12728 at /Users/szalmaf/.julia/v0.4/DataFramesMeta/src/DataFramesMeta.jl:45
 in anonymous at /Users/szalmaf/.julia/v0.4/DataFramesMeta/src/DataFramesMeta.jl:147
 in transform at /Users/szalmaf/.julia/v0.4/DataFramesMeta/src/DataFramesMeta.jl:122

这表明我应该向MyType添加另一个可以处理DataArray的构造函数。是否有另一种更惯用的方式来应用@transform,还是有其他方法可以处理这个地图或转换为oneliner?

1 个答案:

答案 0 :(得分:2)

据我所知,类型构造函数只能返回单个实例,但transform运算符是向量运算。您可以编写一个函数来包装对象构造:

function makeMT(a, b)
  [MyType(a[i],b[i]) for i = 1:size(a,1)]
end

@transform(df, mt = makeMT(:a, :b))

产生:

3x3 DataFrame
| Row | a | b | mt               |
|-----|---|---|------------------|
| 1   | 1 | 6 | MyType(3.0,12.0) |
| 2   | 2 | 7 | MyType(6.0,14.0) |
| 3   | 3 | 8 | MyType(9.0,16.0) |

不幸的是,它不符合您的单线标准。