# Cleanest way to convert DataFrame row into a Vector?

**URL:** <https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531>\
**Category:** Data\
**Tags:** question, dataframes, vector\
**Created:** [August 24, 2017, 1:02am UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531 "2017-08-24T01:02:57Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [August 24, 2017, 1:02am UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/1 "2017-08-24T01:02:57Z")

</div>

I am currently using an ugly hack for it:

```julia
for row in eachrow(df)
  vec = convert(Array, row)' # notice the transpose
end

```

The problem is that vec has type `Matrix` in this case, not `Vector`. I am sure there is a cleaner way?

---

<div class="post-metadata">

**Author:** ![pfitzseb](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pfitzseb/32/45566_2.png) [@pfitzseb](https://discourse.julialang.org/u/pfitzseb)\
**Post date:** [August 24, 2017, 9:04am UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/2 "2017-08-24T09:04:42Z")

</div>

```julia
for row in eachrow(df)
  v = vec(convert(Array, row)) # no transpose necessary
end

```

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [August 24, 2017, 4:44pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/3 "2017-08-24T16:44:41Z")

</div>

Thank you @pfitzseb.

---

<div class="post-metadata">

**Author:** ![Frisus95](https://avatars.discourse-cdn.com/v4/letter/f/77aa72/32.png) [@Frisus95](https://discourse.julialang.org/u/Frisus95)\
**Post date:** [September 10, 2021, 5:45pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/4 "2021-09-10T17:45:10Z")

</div>

> [@juliohm](#):
>
> `'`

Now it looks like it doesn’t work anymore:  
MethodError: Cannot `convert` an object of type  
DataFrameRow{DataFrame, DataFrames.Index} to an object of type  
Array

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [September 10, 2021, 5:51pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/5 "2021-09-10T17:51:04Z")

</div>

A lot of `convert` methods were deprecated. But `collect` works and will remain that way for a long time, given that DataFrames.jl is now at 1.0 (which it wasn’t when this thread started).

---

<div class="post-metadata">

**Author:** ![Frisus95](https://avatars.discourse-cdn.com/v4/letter/f/77aa72/32.png) [@Frisus95](https://discourse.julialang.org/u/Frisus95)\
**Post date:** [September 10, 2021, 5:52pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/6 "2021-09-10T17:52:16Z")

</div>

Yep. Furthermore there’s the method Matrix()

---

<div class="post-metadata">

**Author:** ![rmsmsgood](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rmsmsgood/32/20544_2.png) [@rmsmsgood](https://discourse.julialang.org/u/rmsmsgood)\
**Post date:** [August 2, 2022, 8:06am UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/7 "2022-08-02T08:06:22Z")

</div>

I guess the `collect` function is the best.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 2, 2022, 12:05pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/9 "2022-08-02T12:05:39Z")

</div>

```julia
values(df[2,:])

#or

[values(df[2,:])...]

```

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [August 2, 2022, 1:08pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/10 "2022-08-02T13:08:59Z")

</div>

Splatting like this will be inefficient for data frames with many columns. I would not recommend it as a solution, even if it’s possible.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [August 2, 2022, 3:25pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/11 "2022-08-02T15:25:03Z")

</div>

The following tests seem to show that `collect()` can be 2 x slower for a dataframe with 1000 columns:

```julia
using DataFrames
df = DataFrame(rand(100,1000), :auto)
@btime [v for v in values($df[2,:])] # 68.2 μs (2007 allocs: 70.9 KiB)
@btime [values($df[2,:])...] # 91.9 μs (3007 allocs: 86.6 KiB)
@btime collect($df[2,:]) # 117.8 μs (3985 allocs: 85.9 KiB)

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 2, 2022, 4:54pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/12 "2022-08-02T16:54:26Z")

</div>

it seems that what makes the difference is the values (…) function

```julia
julia> @btime collect(values($df[2,:]));
  56.800 μs (2006 allocations: 63.03 KiB)

julia> @btime [v for v in values($df[2,:])] ;
  59.800 μs (2007 allocations: 70.91 KiB)

julia> @btime [values($df[2,:])...] ;        
  77.600 μs (3007 allocations: 86.59 KiB)

julia> @btime [v for v in $df[2,:]] ;
  103.500 μs (3983 allocations: 85.83 KiB)

```

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [August 2, 2022, 9:39pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/13 "2022-08-02T21:39:56Z")

</div>

This benchmarks ~1.25 faster for the few cases I tested.  
(all the values in the row need to be of the same concrete type)

```julia
function dfrow(df::DataFrame, row)
    T = typeof(df[row,1])
    Array{T,1}(df[row,:])
end

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 3, 2022, 1:42pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/14 "2022-08-03T13:42:42Z")

</div>

maybe I mess with the types or misunderstand what you say, but it seems that removing the limitations on the type of the columns does not penalize the performance.  
rather.

```julia
julia> @btime Vector{Float64}(df[2,:]);
  41.400 μs (1491 allocations: 31.27 KiB)

julia> @btime Vector{Any}(df[2,:]);
  28.500 μs (1002 allocations: 23.62 KiB)

```

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [August 3, 2022, 2:00pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/15 "2022-08-03T14:00:38Z")

</div>

> [@rocco\_sprmnt21](#):
>
> `@btime Vector{Float64}(df[2,:]);`

indeed … how unexpected

```julia
dfrow(df::DataFrame, row::Int) = Array{Any, 1}(df[row, :])

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 3, 2022, 2:14pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/16 "2022-08-03T14:14:13Z")

</div>

forgive me but my English does not allow me to grasp the nuances of your observation.  
Could you explain the meaning more explicitly?  
I take this opportunity to ask if an implementation of `values ()` in the following way is not preferable.

```julia
_values(dfr)=tuple(Vector{Any}(dfr))

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [August 3, 2022, 2:18pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/17 "2022-08-03T14:18:06Z")

</div>

> [@rocco\_sprmnt21](#):
>
> `Vector{Any}(df[2,:])`

If I understood Julia’s performance tips correctly, parametrizing with Any avoids runtime type checking and is therefore faster. However, if we need to do calculations with such an array, we will pay the performance price later.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [August 3, 2022, 3:01pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/18 "2022-08-03T15:01:08Z")

</div>

in this way it preserves the type and much of the performance

```julia
df = DataFrame(rand(100,1000), :auto)
rowtovec(df::DataFrame,row::Int)=[df[row,i] for i in 1:ncol(df)]

julia> @btime rowtovec(df,2)
  31.400 μs (1003 allocations: 23.64 KiB)
1000-element Vector{Float64}:
 0.31623289609155747
 0.08624728904277756

```

---

<div class="post-metadata">

**Author:** ![JeffreySarnoff](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jeffreysarnoff/32/1980_2.png) [@JeffreySarnoff](https://discourse.julialang.org/u/JeffreySarnoff)\
**Post date:** [August 3, 2022, 4:21pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/19 "2022-08-03T16:21:37Z")

</div>

> [@rocco\_sprmnt21](#):
>
> `rowtovec(df::DataFrame,row::Int)=[df[row,i] for i in 1:ncol(df)]`

this does appear to outperform the others while avoiding {Any}

---

<div class="post-metadata">

**Author:** ![tecosaur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tecosaur/32/23206_2.png) [@tecosaur](https://discourse.julialang.org/u/tecosaur)\
**Post date:** [February 10, 2023, 6:51am UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/20 "2023-02-10T06:51:55Z")

</div>

I wondered why `[df[row,i] for i in 1:ncol(df)]` would perform better, and after confirmed it looked at the output of `Meta.@lower`. What surprises me is that while it looks like it should be equivalent to `collect(Base.Generator(i -> df[2, i], 1:ncol(df)))`, this form is ~60% slower (48μs vs 30μs).

For context, here’s `Meta.@lower [df[row,i] for i in 1:ncol(df)]`

```julia
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ $(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ global var"#76#77"
│ const var"#76#77"
│ %3 = Core._structtype(Main, Symbol("#76#77"), Core.svec(), Core.svec(), Core.svec(), false, 0)
│ var"#76#77" = %3
│ Core._setsuper!(var"#76#77", Core.Function)
│ Core._typebody!(var"#76#77", Core.svec())
└── return nothing
)))
│ %2 = Core.svec(var"#76#77", Core.Any)
│ %3 = Core.svec()
│ %4 = Core.svec(%2, %3, $(QuoteNode(:(#= none:0 =#))))
│ $(Expr(:method, false, :(%4), CodeInfo(
    @ none within `none`
1 ─ %1 = Base.getindex(df, 2, i)
└── return %1
)))
│ #76 = %new(var"#76#77")
│ %7 = #76
│ %8 = ncol(df)
│ %9 = 1:%8
│ %10 = Base.Generator(%7, %9)
│ %11 = Base.collect(%10)
└── return %11
))))

```

And here’s `Meta.@lower collect(Base.Generator(i -> df[2, i], 1:ncol(df)))`

```julia
:($(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ $(Expr(:thunk, CodeInfo(
    @ none within `top-level scope`
1 ─ global var"#46#47"
│ const var"#46#47"
│ %3 = Core._structtype(Main, Symbol("#46#47"), Core.svec(), Core.svec(), Core.svec(), false, 0)
│ var"#46#47" = %3
│ Core._setsuper!(var"#46#47", Core.Function)
│ Core._typebody!(var"#46#47", Core.svec())
└── return nothing
)))
│ %2 = Core.svec(var"#46#47", Core.Any)
│ %3 = Core.svec()
│ %4 = Core.svec(%2, %3, $(QuoteNode(:(#= REPL[1]:1 =#))))
│ $(Expr(:method, false, :(%4), CodeInfo(
    @ REPL[1]:1 within `none`
1 ─ %1 = Base.getindex(df, 2, i)
└── return %1
)))
│ %6 = Base.getproperty(Base, :Generator)
│ #46 = %new(var"#46#47")
│ %8 = #46
│ %9 = ncol(df)
│ %10 = 1:%9
│ %11 = (%6)(%8, %10)
│ %12 = collect(%11)
└── return %12
))))

```

The only difference I see is that instead of `%10 = Base.Generator(%7, %9)`, the second expansion has:

```julia
│ %6 = Base.getproperty(Base, :Generator)
│ #46 = %new(var"#46#47")
...
│ %11 = (%6)(%8, %10)

```

This seems rather strange to me…

---

<div class="post-metadata">

**Author:** ![tom-plaa](https://avatars.discourse-cdn.com/v4/letter/t/d26b3c/32.png) [@tom-plaa](https://discourse.julialang.org/u/tom-plaa)\
**Post date:** [February 22, 2023, 3:03pm UTC](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531/21 "2023-02-22T15:03:17Z")

</div>

@tecosaur that seems pretty intriguing to me, I’ll also wait for someone more knowledgeable to chime in here

[Next page](https://discourse.julialang.org/t/cleanest-way-to-convert-dataframe-row-into-a-vector/5531.md?page=2)
