class_docstr: Stores all actual data and typing information for an entityset
  
  Attributes:
      id
      dataframe_dict
      relationships
      time_type
  
  Properties:
      metadata
class_docstr_tok: ["Stores","all","actual","data","and","typing","information","for","an","entityset","Attributes",":","id","dataframe_dict","relationships","time_type","Properties",":","metadata"]
docstr: Add a new relationship between dataframes in the entityset. Relationships can be specified
  by passing dataframe and columns names or by passing a :class:`.Relationship` object.
  
  Args:
      parent_dataframe_name (str): Name of the parent dataframe in the EntitySet. Must be specified
          if relationship is not.
      parent_column_name (str): Name of the parent column. Must be specified if relationship is not.
      child_dataframe_name (str): Name of the child dataframe in the EntitySet. Must be specified
          if relationship is not.
      child_column_name (str): Name of the child column. Must be specified if relationship is not.
      relationship (Relationship): Instance of new relationship to be added. Must be specified
          if dataframe and column names are not supplied.
docstr_tok: ["Add","a","new","relationship","between","dataframes","in","the","entityset",".","Relationships","can","be","specified","by","passing","dataframe","and","columns","names","or","by","passing","a",":","class",":","`",".Relationship","`","object",".","Args",":","parent_dataframe_name","(","str",")",":","Name","of","the","parent","dataframe","in","the","EntitySet",".","Must","be","specified","if","relationship","is","not",".","parent_column_name","(","str",")",":","Name","of","the","parent","column",".","Must","be","specified","if","relationship","is","not",".","child_dataframe_name","(","str",")",":","Name","of","the","child","dataframe","in","the","EntitySet",".","Must","be","specified","if","relationship","is","not",".","child_column_name","(","str",")",":","Name","of","the","child","column",".","Must","be","specified","if","relationship","is","not",".","relationship","(","Relationship",")",":","Instance","of","new","relationship","to","be","added",".","Must","be","specified","if","dataframe","and","column","names","are","not","supplied","."]
code: def add_relationship(
      self,
      parent_dataframe_name=None,
      parent_column_name=None,
      child_dataframe_name=None,
      child_column_name=None,
      relationship=None,
  ):
      """Add a new relationship between dataframes in the entityset. Relationships can be specified
      by passing dataframe and columns names or by passing a :class:`.Relationship` object.
  
      Args:
          parent_dataframe_name (str): Name of the parent dataframe in the EntitySet. Must be specified
              if relationship is not.
          parent_column_name (str): Name of the parent column. Must be specified if relationship is not.
          child_dataframe_name (str): Name of the child dataframe in the EntitySet. Must be specified
              if relationship is not.
          child_column_name (str): Name of the child column. Must be specified if relationship is not.
          relationship (Relationship): Instance of new relationship to be added. Must be specified
              if dataframe and column names are not supplied.
      """
      if relationship and (
          parent_dataframe_name
          or parent_column_name
          or child_dataframe_name
          or child_column_name
      ):
          raise ValueError(
              "Cannot specify dataframe and column name values and also supply a Relationship",
          )
  
      if not relationship:
          relationship = Relationship(
              self,
              parent_dataframe_name,
              parent_column_name,
              child_dataframe_name,
              child_column_name,
          )
      if relationship in self.relationships:
          warnings.warn(
              "Not adding duplicate relationship: " + str(relationship)
          )
          return self
  
      # _operations?
  
      # this is a new pair of dataframes
      child_df = relationship.child_dataframe
      child_column = relationship._child_column_name
      if child_df.ww.index == child_column:
          msg = "Unable to add relationship because child column '{}' in '{}' is also its index"
          raise ValueError(msg.format(child_column, child_df.ww.name))
      parent_df = relationship.parent_dataframe
      parent_column = relationship._parent_column_name
  
      if parent_df.ww.index != parent_column:
          parent_df.ww.set_index(parent_column)
  
      # Empty dataframes (as a result of accessing metadata)
      # default to object dtypes for categorical columns, but
      # indexes/foreign keys default to ints. In this case, we convert
      # the empty column's type to int
      if isinstance(child_df, pd.DataFrame) and (
          child_df.empty
          and child_df[child_column].dtype == object
          and parent_df.ww.columns[parent_column].is_numeric
      ):
          child_df.ww[child_column] = pd.Series(
              name=child_column, dtype=np.int64
          )
  
      parent_ltype = parent_df.ww.logical_types[parent_column]
      child_ltype = child_df.ww.logical_types[child_column]
      if parent_ltype != child_ltype:
          difference_msg = ""
          if str(parent_ltype) == str(child_ltype):
              difference_msg = (
                  "There is a conflict between the parameters. "
              )
  
          warnings.warn(
              f"Logical type {child_ltype} for child column {child_column} does not match "
              f"parent column {parent_column} logical type {parent_ltype}. {difference_msg}"
              "Changing child logical type to match parent.",
          )
          child_df.ww.set_types(
              logical_types={child_column: parent_ltype}
          )
  
      if "foreign_key" not in child_df.ww.semantic_tags[child_column]:
          child_df.ww.add_semantic_tags({child_column: "foreign_key"})
  
      self.relationships.append(relationship)
      self.reset_data_description()
      return self
  
imports: import copy
  import logging
  import warnings
  from collections import defaultdict
  import numpy
  import pandas
  from woodwork import init_series
  from woodwork.logical_types import Datetime, LatLong
  from featuretools.entityset import deserialize, serialize
  from featuretools.entityset.relationship import Relationship, RelationshipPath
  from featuretools.feature_base.feature_base import _ES_REF
  from featuretools.utils.gen_utils import Library, import_or_none, is_instance
  from featuretools.utils.plot_utils import check_graphviz, get_graphviz_format, save_graph
  from featuretools.utils.wrangle import _check_timedelta
label_desc: Use image node_id 18 for calling the EntitySet obj's underlying member method code with example usage: obj.add_relationship(parent_dataframe_name, parent_column_name, child_dataframe_name, child_column_name, relationship) and returns: self, self