# How to change field names and types of a DataFrame

**URL:** <https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991>\
**Category:** Data\
**Tags:** question\
**Created:** [July 30, 2020, 4:46pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991 "2020-07-30T16:46:38Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [July 30, 2020, 4:46pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/1 "2020-07-30T16:46:38Z")

</div>

I imported a `xlsx` file to an array `a` using `XLSX.jl`. But now I have no real names for the fields in `df` and the types are all `Any`.  
I changed names using `rename!` but I don’t know how to change types respectively to `String`, `Int64` and `Float64`. Is it possible to import a vector of element types?  
Is there a better method to go from `xlsx` to a `DataFrame` importing the row heading and types?

```julia
using DataFrames
# using an array
a = ["a" 2 4.2; "b" 5 6.7; "c" 3 8.9]
df = DataFrame(a)
# How to change names and types of DataFrame?
vec_of_names = ["name", "2004", "2020"]
rename!(df, vec_of_your_new_names)

```

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [July 30, 2020, 5:27pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/2 "2020-07-30T17:27:22Z")

</div>

Someting like

```julia
df[!, :x2] = convert.(Int, df[:, :x2])

```

will change types types. Note the `!` and `:`. See

> [@DataFrames: convert column data type](https://discourse.julialang.org/t/dataframes-convert-column-data-type/35522):
>
> Was looking around, but didn’t find an answer. Specifically, I have a DataFrame and one column has data type Int64; it has the unique values 0 and 1 (meaning obviously false and true). What is the easiest quickest way to have the column including its entries converted to the boolean data type? I thought about a kind of loop, but are there already existing functions available that I should know of? More generally, please explain how to best tackle this (especially conceptually), if using a se…

---

<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:** [July 30, 2020, 5:28pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/3 "2020-07-30T17:28:56Z")

</div>

The newest version of `XLSX.jl` should allow very easy conversion to a data frame. See the docs [here](https://felipenoris.github.io/XLSX.jl/stable/tutorial/#Read-Tabular-Data-1).

---

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [July 30, 2020, 5:50pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/4 "2020-07-30T17:50:13Z")

</div>

It’s strange. The first one (`name`) works but not the other two.

```julia
df[!, :name] = convert.(String, df[:, :name])
df[!, :2004] = convert.(Int, df[:, :2004])
df[!, :2020] = convert.(Float, df[:, :2020])

```

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [July 30, 2020, 5:57pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/5 "2020-07-30T17:57:25Z")

</div>

I don’t think `:2004` is a valid column name. I would rename it (or you can probably access it as a string name).

---

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [July 30, 2020, 6:06pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/6 "2020-07-30T18:06:06Z")

</div>

You’re right. I had to change column names. Now it works.

```julia
df[!, :name] = convert.(String, df[:, :name])
df[!, :y2004] = convert.(Int, df[:, :y2004])
df[!, :y2020] = convert.(Float64, df[:, :y2020])

```

But I can access it as a string name:  
`df[!, "2020"] = convert.(Float64, df[:, "2020"])`  
Maybe there’s a way to put this on a line 🙂

---

<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:** [July 30, 2020, 6:22pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/7 "2020-07-30T18:22:00Z")

</div>

You should file an issue about this in DataFrames. a `narrow_types!` function would be nice to have, since this comes up a decent amount.

---

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [July 30, 2020, 6:46pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/8 "2020-07-30T18:46:50Z")

</div>

Do you mean something like

```julia
v1 = [:name :y2004 "2020"]
v2 = [String Int Float64]

df[!, v1] = convert.(v2, df[:, v1])

```

Note: this doesn’t work.

---

<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:** [July 30, 2020, 6:56pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/9 "2020-07-30T18:56:09Z")

</div>

1. You should learn the difference between vectors and matrices. You should be working with vectors here, `[:name, :y2004, "2020"]`, note, the commas instead of spaces.
2. It’s not clear what your line is trying to accomplish.

I mean something like the following:

```julia
julia> df = DataFrame(x = Any[rand() for i in 1:10], y = Union{Float64, Missing}[rand() for i in 1:10]);

julia> function narrow_types!(df)
           for c in names(df)
               df[!, c] = identity.(df[!, c])
           end
           return df
       end
narrow_types! (generic function with 2 methods)

julia> narrow_types!(df)
10×2 DataFrame
│ Row │ x │ y │
│ │ Float64 │ Float64 │
├─────┼───────────┼───────────┤
│ 1 │ 0.234185 │ 0.0427855 │
│ 2 │ 0.519789 │ 0.123238 │
│ 3 │ 0.838223 │ 0.414821 │
│ 4 │ 0.436736 │ 0.0125951 │
│ 5 │ 0.981439 │ 0.867722 │
│ 6 │ 0.0135416 │ 0.547298 │
│ 7 │ 0.9429 │ 0.966585 │
│ 8 │ 0.333247 │ 0.379245 │
│ 9 │ 0.567072 │ 0.208785 │
│ 10 │ 0.114606 │ 0.256162 │

```

---

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [July 30, 2020, 7:55pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/10 "2020-07-30T19:55:27Z")

</div>

1. Sorry. Thank you;
2. I was trying to use a vector of names and a vector of types to change the names and types of a `DataFrame`.

---

<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:** [July 30, 2020, 7:59pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/11 "2020-07-30T19:59:32Z")

</div>

No problem.

I think ultimately you want Julia to take care of the types of columns, using the function above.

If you want to specify the types themselves, try this:

```julia
julia> function convert_types(df, colstypes)
           for (c, t) in colstypes
               df[!, c] = convert.(t, df[!, c])
           end
           df
       end
convert_types (generic function with 1 method)

julia> convert_types(df, [:x => Float64, :y => Float64])
10×2 DataFrame
│ Row │ x │ y │
│ │ Float64 │ Float64 │
├─────┼──────────┼──────────┤
│ 1 │ 0.834294 │ 0.463568 │
│ 2 │ 0.60386 │ 0.517164 │
│ 3 │ 0.820777 │ 0.994759 │
│ 4 │ 0.372805 │ 0.501976 │
│ 5 │ 0.70668 │ 0.707915 │
│ 6 │ 0.6946 │ 0.377697 │
│ 7 │ 0.182847 │ 0.958645 │
│ 8 │ 0.116744 │ 0.53444 │
│ 9 │ 0.393341 │ 0.39792 │
│ 10 │ 0.862753 │ 0.17667 │

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [July 30, 2020, 8:07pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/12 "2020-07-30T20:07:50Z")

</div>

I did this same mistake the other day, it is a little misleading but:

```julia
julia> typeof(:1000)
Int64

```

A colon followed by a number is not a `Symbol`, it is just the number. To get a symbol you would need `Symbol("1000")`.

---

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [July 30, 2020, 8:10pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/13 "2020-07-30T20:10:12Z")

</div>

Yes. It is similar to what I wanted. It works in my case:  
`convert_types(df, [:name => String, :y2004 => Int, "2020" => Float64])`

---

<div class="post-metadata">

**Author:** ![sbacelar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sbacelar/32/4359_2.png) [@sbacelar](https://discourse.julialang.org/u/sbacelar)\
**Post date:** [July 30, 2020, 8:12pm UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/14 "2020-07-30T20:12:11Z")

</div>

See above. When I use a string “2020” instead of `:y2020` also works.

---

<div class="post-metadata">

**Author:** ![nilshg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nilshg/32/2283_2.png) [@nilshg](https://discourse.julialang.org/u/nilshg)\
**Post date:** [August 1, 2020, 10:31am UTC](https://discourse.julialang.org/t/how-to-change-field-names-and-types-of-a-dataframe/43991/15 "2020-08-01T10:31:06Z")

</div>

For future reference, `XLSX.readtable` also has a `infer_eltypes` kwarg that should give back properly typed columns for your DataFrame: [API Reference · XLSX.jl](https://felipenoris.github.io/XLSX.jl/stable/api/#XLSX.readtable)
