# Dictionary of dictionaries as decision tree

**URL:** <https://discourse.julialang.org/t/dictionary-of-dictionaries-as-decision-tree/108783>\
**Category:** General Usage\
**Tags:** question, recursion, decision-trees\
**Created:** [January 14, 2024, 3:04am UTC](https://discourse.julialang.org/t/dictionary-of-dictionaries-as-decision-tree/108783 "2024-01-14T03:04:46Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![leoflotor](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/leoflotor/32/35345_2.png) [@leoflotor](https://discourse.julialang.org/u/leoflotor)\
**Post date:** [January 14, 2024, 3:04am UTC](https://discourse.julialang.org/t/dictionary-of-dictionaries-as-decision-tree/108783/1 "2024-01-14T03:04:46Z")

</div>

Hi!

I am trying to do a decision tree using my implementation of ID3 but I am having some problems with one of my functions.

For example, I have the following data frame:

```julia
julia> df
14×6 DataFrame
 Row │ pa as ic aa oa af      
     │ String7 String7 String7 String3 String3 String3 
─────┼──────────────────────────────────────────────────────
   1 │ alta alto alto no no si
   2 │ alta alto alto si no si
   3 │ baja alto bajo no no si
   4 │ media alto alto no si no
   5 │ media bajo alto si si no
   6 │ baja bajo alto si si si
   7 │ alta bajo alto si no si
   8 │ alta bajo bajo no si si
   9 │ alta alto bajo si si no
  10 │ baja bajo alto si si si
  11 │ media bajo bajo si si si
  12 │ alta bajo alto si si no
  13 │ baja alto alto si si si
  14 │ baja alto bajo no no si

```

The class is `af`. From within my code I wrote a function that “creates” a tree, although it is not done properly, but it gets the job done for my purposes.

First, I load the database file:

```julia
julia> df = dt.read_database("data/administar_farmaco.csv"; dropcols=[:n])

```

Then I can just generate the tree as:

```julia
julia> tree = dt.tree("af", df)
4-element Vector{Any}:
 "pa"
 Any[InlineStrings.String7("alta"), "oa", Any[InlineStrings.String3("no"), InlineStrings.String3["si"]], Any[InlineStrings.String3("si"), "aa", Any[InlineStrings.String3("no"), InlineStrings.String3["si"]], Any[InlineStrings.String3("si"), InlineStrings.String3["no"]]]]
 Any[InlineStrings.String7("baja"), InlineStrings.String3["si"]]
 Any[InlineStrings.String7("media"), "ic", Any[InlineStrings.String7("alto"), InlineStrings.String3["no"]], Any[InlineStrings.String7("bajo"), InlineStrings.String3["si"]]]

```

I was able to write a function that takes that output, `tree`, and parses it:

```julia
julia> dt.preetyprint(tree)
pa
alta
	oa
	no	si
	si
		aa
		no	si
		si	no
baja	si
media
	ic
	alto	no
	bajo	si

```

Which can be more clearly understood if I just format it a little it by hand as:

```julia
pa
 |--- alta
       |--- oa
            |--- no --- si
            |--- si
                 |--- aa
                      |--- no --- si
                      |--- si --- no
 |--- baja --- si
 |--- media
      | --- ic
             |--- alto --- no
             |--- bajo --- si

```

It’s not pretty haha but it gets the job done to allow me to visualize the decision tree.

The problem is that I wanted to create a dictionary in the first place where each entry was another dictionary.

I found something similar to what I want to achieve here [in this kaggle notebook](https://www.kaggle.com/code/tareqjoy/easy-id3/notebook?source=post_page-----4822bbfdd88f--------------------------------) written in Python.

The owner of that notebook achieved to have each key of each dictionary as a node of the tree I showed above. The image attached below shows what I mean.

![image](https://global.discourse-cdn.com/julialang/original/3X/a/6/a6348bb4178e1a78d9eaa42a410beba8d434bfcc.png)

Here is my code attached: [DecisionTrees.jl](https://discourse.julialang.org/uploads/short-url/yO6HGSO6eRAYdByMEF0RtLYEGPD.jl) (5.4 KB)

Currently, I have a function that attempts to create a dictionary of dictionaries but… Well, I couldn’t figure it out. I called that function `tree_dict` for lack of a better name.

Can anyone point me in the right direction on how could I implement it with my current code?

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [January 14, 2024, 12:59pm UTC](https://discourse.julialang.org/t/dictionary-of-dictionaries-as-decision-tree/108783/2 "2024-01-14T12:59:32Z")

</div>

Just skimming at your code, it seems that `preetyprint` has already the structure you could use. Except, that it prints instead of creating a nested data structure.  
Just start from there: Adapt the base case to return values you want at the leaves and collect the results of the recursive calls in the `for`-loop into a dictionary (would use a comprehension for that).

---

<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:** [January 14, 2024, 1:38pm UTC](https://discourse.julialang.org/t/dictionary-of-dictionaries-as-decision-tree/108783/3 "2024-01-14T13:38:15Z")

</div>

try this

```julia
tree = [
 "pa",
 Any["alta", "oa", Any["no", ["si"]], Any["si", "aa", Any["no", ["si"]], Any["si", ["no"]]]],
 Any["baja", ["si"]],
 Any["media", "ic", Any["alto", ["no"]], Any["bajo", ["si"]]]]

recdic(tree)=Dict(tree[1]=>Dict([first(vv)=>(last(vv) isa Array{String} ? only(last(vv)) : recdic(vv[2:end])) for vv in tree[2: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:** [January 14, 2024, 5:33pm UTC](https://discourse.julialang.org/t/dictionary-of-dictionaries-as-decision-tree/108783/4 "2024-01-14T17:33:22Z")

</div>

```julia
julia> walk3(tree, lev=0) = join(['\n'*" "^lev*"|.."*tree[1],join(['\n'*" "^(lev+1)*"|.."*first(vv)*(last(vv) isa Array{String} ? "---"*only(last(vv)) : walk3(vv[2:end],lev+2)) for vv in tree[2:end]])])
walk3 (generic function with 2 methods)

julia> println(walk3(tree))

|..pa
     |..alta
          |..oa
               |..no---si
               |..si
                    |..aa
                         |..no---si
                         |..si---no
     |..baja---si
     |..media
          |..ic
               |..alto---no
               |..bajo---si

```
