docstr: Create an arrow binary that can be loaded and manipulated from memory, with
  each column being a dictionary array of `str` values and `int` indices.
  
  Args:
      names (list): a list of str column names
      data (list:tuple): a list of tuples, the first value being a list of indices,
          and the second value being a list of values.
      types (list:list:pyarrow.func): a list of lists, containing the indices type and
          dictionary value type for each array.
      legacy (bool): if True, use legacy IPC format (pre-pyarrow 0.15). Defaults to False.
  
  Returns:
      bytes : a bytes object containing the arrow-serialized output.
docstr_tok: ["Create","an","arrow","binary","that","can","be","loaded","and","manipulated","from","memory",",","with","each","column","being","a","dictionary","array","of","`","str","`","values","and","`","int","`","indices",".","Args",":","names","(","list",")",":","a","list","of","str","column","names","data","(","list",":","tuple",")",":","a","list","of","tuples",",","the","first","value","being","a","list","of","indices",",","and","the","second","value","being","a","list","of","values",".","types","(","list",":","list",":","pyarrow.func",")",":","a","list","of","lists",",","containing","the","indices","type","and","dictionary","value","type","for","each","array",".","legacy","(","bool",")",":","if","True",",","use","legacy","IPC","format","(","pre-pyarrow","0.15",")",".","Defaults","to","False",".","Returns",":","bytes",":","a","bytes","object","containing","the","arrow-serialized","output","."]
code: def make_dictionary_arrow(names, data, types=None, legacy=False):
      """Create an arrow binary that can be loaded and manipulated from memory, with
      each column being a dictionary array of `str` values and `int` indices.
  
      Args:
          names (list): a list of str column names
          data (list:tuple): a list of tuples, the first value being a list of indices,
              and the second value being a list of values.
          types (list:list:pyarrow.func): a list of lists, containing the indices type and
              dictionary value type for each array.
          legacy (bool): if True, use legacy IPC format (pre-pyarrow 0.15). Defaults to False.
  
      Returns:
          bytes : a bytes object containing the arrow-serialized output.
      """
      stream = pa.BufferOutputStream()
  
      arrays = []
      for idx, column in enumerate(data):
          indice_type = pa.int64()
          value_type = pa.string()
  
          if types is not None:
              indice_type = types[idx][0]
              value_type = types[idx][1]
  
          indices = pa.array(column[0], type=indice_type)
          values = pa.array(column[1], type=value_type)
          parray = pa.DictionaryArray.from_arrays(indices, values)
          arrays.append(parray)
  
      batch = pa.RecordBatch.from_arrays(arrays, names)
      table = pa.Table.from_batches([batch])
      writer = pa.RecordBatchStreamWriter(
          stream, table.schema, use_legacy_format=legacy
      )
  
      writer.write_table(table)
      writer.close()
      return stream.getvalue().to_pybytes()
  
imports: from datetime import datetime
  import numpy
  import pandas
  import pyarrow
  from pytest import fixture
  from random import random, randint, choice
  from faker import Faker
label_desc: Use image node_id 3 for calling the Util obj's underlying member method code with example usage: obj.make_dictionary_arrow(names, data, types, legacy) and returns: stream