We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
DataCollector bug
Found a minor bug in DataCollector, where some variables are not initialized in the instance, and become class variables instead. Fixing.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mesa/datacollection.py`
Content:
```
1 '''
2 Mesa Data Collection Module
3 =====================================================
4 
5 DataCollector is meant to provide a simple, standard way to collect data
6 generated by a Mesa model. It collects three types of data: model-level data,
7 agent-level data, and tables.
8 
9 A DataCollector is instantiated with two dictionaries of reporter names and
10 associated functions for each, one for model-level data and one for
11 agent-level data; a third dictionary provides table names and columns.
12 
13 When the collect() method is called, each model-level function is called, with
14 the model as the argument, and the results associated with the relevant
15 variable. Then the agent-level functions are called on each
16 agent in the model scheduler.
17 
18 Additionally, other objects can write directly to tables by passing in an
19 appropriate dictionary object for a table row.
20 
21 The DataCollector then stores the data it collects in dictionaries:
22     * model_vars maps each reporter to a list of its values
23     * agent_vars maps each reporter to a list of lists, where each nested list
24     stores (agent_id, value) pairs.
25     * tables maps each table to a dictionary, with each column as a key with a
26     list as its value.
27 
28 Finally, DataCollector can create a pandas DataFrame from each collection.
29 
30 The default DataCollector here makes several assumptions:
31     * The model has a schedule object called 'schedule'
32     * The schedule has an agent list called agents
33     * For collecting agent-level variables, agents must have a unique_id
34 '''
35 from collections import defaultdict
36 import pandas as pd
37 
38 
39 class DataCollector(object):
40     '''
41     Class for collecting data generated by a Mesa model.
42 
43     A DataCollector is instantiated with dictionaries of names of model- and
44     agent-level variables to collect, associated with functions which actually
45     collect them. When the collect(...) method is called, it executes these
46     functions one by one and stores the results.
47     '''
48     model_reporters = {}
49     agent_reporters = {}
50 
51     model_vars = {}
52     agent_vars = {}
53     tables = {}
54 
55     model = None
56 
57     def __init__(self, model_reporters={}, agent_reporters={}, tables={}):
58         '''
59         Instantiate a DataCollector with lists of model and agent reporters.
60 
61         Both model_reporters and agent_reporters accept a dictionary mapping a
62         variable name to a method used to collect it.
63         For example, if there was only one model-level reporter for number of
64         agents, it might look like:
65             {"agent_count": lambda m: m.schedule.get_agent_count() }
66         If there was only one agent-level reporter (e.g. the agent's energy),
67         it might look like this:
68             {"energy": lambda a: a.energy}
69 
70         The tables arg accepts a dictionary mapping names of tables to lists of
71         columns. For example, if we want to allow agents to write their age
72         when they are destroyed (to keep track of lifespans), it might look
73         like:
74             {"Lifespan": ["unique_id", "age"]}
75 
76         Args:
77             model_reporters: Dictionary of reporter names and functions.
78             agent_reporters: Dictionary of reporter names and functions.
79         '''
80 
81         self.model_reporters = {}
82         self.agent_reporters = {}
83         self.tables = {}
84 
85         for name, func in model_reporters.items():
86             self._new_model_reporter(name, func)
87 
88         for name, func in agent_reporters.items():
89             self._new_agent_reporter(name, func)
90 
91         for name, columns in tables.items():
92             self._new_table(name, columns)
93 
94     def _new_model_reporter(self, reporter_name, reporter_function):
95         '''
96         Add a new model-level reporter to collect.
97         Args:
98             reporter_name: Name of the model-level variable to collect.
99             reporter_function: Function object that returns the variable when
100                                given a model instance.
101         '''
102 
103         self.model_reporters[reporter_name] = reporter_function
104         self.model_vars[reporter_name] = []
105 
106     def _new_agent_reporter(self, reporter_name, reporter_function):
107         '''
108         Add a new agent-level reporter to collect.
109         Args:
110             reporter_name: Name of the agent-level variable to collect.
111             reporter_function: Function object that returns the variable when
112                                given an agent object.
113         '''
114         self.agent_reporters[reporter_name] = reporter_function
115         self.agent_vars[reporter_name] = []
116 
117     def _new_table(self, table_name, table_columns):
118         '''
119         Add a new table that objects can write to.
120         Args:
121             table_name: Name of the new table.
122             table_columns: List of columns to add to the table.
123         '''
124         new_table = {column: [] for column in table_columns}
125         self.tables[table_name] = new_table
126 
127     def collect(self, model):
128         '''
129         Collect all the data for the given model object.
130         '''
131         if self.model_reporters:
132             for var, reporter in self.model_reporters.items():
133                 self.model_vars[var].append(reporter(model))
134 
135         if self.agent_reporters:
136             for var, reporter in self.agent_reporters.items():
137                 agent_records = []
138                 for agent in model.schedule.agents:
139                     agent_records.append((agent.unique_id, reporter(agent)))
140                 self.agent_vars[var].append(agent_records)
141 
142     def add_table_row(self, table_name, row, ignore_missing=False):
143         '''
144         Add a row dictionary to a specific table.
145 
146         Args:
147             table_name: Name of the table to append a row to.
148             row: A dictionary of the form {column_name: value...}
149             ignore_missing: If True, fill any missing columns with Nones;
150                             if False, throw an error if any columns are missing
151         '''
152         if table_name not in self.tables:
153             raise Exception("Table does not exist.")
154 
155         for column in self.tables[table_name]:
156             if column in row:
157                 self.tables[table_name][column].append(row[column])
158             elif ignore_missing:
159                 self.tables[table_name][column].append(None)
160             else:
161                 raise Exception("Could not insert row with missing column")
162 
163     def get_model_vars_dataframe(self):
164         '''
165         Create a pandas DataFrame from the model variables.
166         The DataFrame has one column for each model variable, and the index is
167         (implicitly) the model tick.
168         '''
169         return pd.DataFrame(self.model_vars)
170 
171     def get_agent_vars_dataframe(self):
172         '''
173         Create a pandas DataFrame from the agent variables.
174         The DataFrame has one column for each variable, with two additional
175         columns for tick and agent_id.
176         '''
177 
178         data = defaultdict(dict)
179         for var, records in self.agent_vars.items():
180             for step, entries in enumerate(records):
181                 for entry in entries:
182                     agent_id = entry[0]
183                     val = entry[1]
184                     data[(step, agent_id)][var] = val
185         df = pd.DataFrame.from_dict(data, orient="index")
186         df.index.names = ["Step", "AgentID"]
187         return df
188 
189     def get_table_dataframe(self, table_name):
190         '''
191         Create a pandas DataFrame from a particular table.
192 
193         Args:
194             table_name: The name of the table to convert.
195         '''
196         if table_name not in self.tables:
197             raise Exception("No such table.")
198         return pd.DataFrame(self.tables[table_name])
199
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mesa/datacollection.py b/mesa/datacollection.py
--- a/mesa/datacollection.py
+++ b/mesa/datacollection.py
@@ -80,6 +80,9 @@
 
         self.model_reporters = {}
         self.agent_reporters = {}
+
+        self.model_vars = {}
+        self.agent_vars = {}
         self.tables = {}
 
         for name, func in model_reporters.items():

{"golden_diff": "diff --git a/mesa/datacollection.py b/mesa/datacollection.py\n--- a/mesa/datacollection.py\n+++ b/mesa/datacollection.py\n@@ -80,6 +80,9 @@\n \n         self.model_reporters = {}\n         self.agent_reporters = {}\n+\n+        self.model_vars = {}\n+        self.agent_vars = {}\n         self.tables = {}\n \n         for name, func in model_reporters.items():\n", "issue": "DataCollector bug\nFound a minor bug in DataCollector, where some variables are not initialized in the instance, and become class variables instead. Fixing.\n\n", "before_files": [{"content": "'''\nMesa Data Collection Module\n=====================================================\n\nDataCollector is meant to provide a simple, standard way to collect data\ngenerated by a Mesa model. It collects three types of data: model-level data,\nagent-level data, and tables.\n\nA DataCollector is instantiated with two dictionaries of reporter names and\nassociated functions for each, one for model-level data and one for\nagent-level data; a third dictionary provides table names and columns.\n\nWhen the collect() method is called, each model-level function is called, with\nthe model as the argument, and the results associated with the relevant\nvariable. Then the agent-level functions are called on each\nagent in the model scheduler.\n\nAdditionally, other objects can write directly to tables by passing in an\nappropriate dictionary object for a table row.\n\nThe DataCollector then stores the data it collects in dictionaries:\n    * model_vars maps each reporter to a list of its values\n    * agent_vars maps each reporter to a list of lists, where each nested list\n    stores (agent_id, value) pairs.\n    * tables maps each table to a dictionary, with each column as a key with a\n    list as its value.\n\nFinally, DataCollector can create a pandas DataFrame from each collection.\n\nThe default DataCollector here makes several assumptions:\n    * The model has a schedule object called 'schedule'\n    * The schedule has an agent list called agents\n    * For collecting agent-level variables, agents must have a unique_id\n'''\nfrom collections import defaultdict\nimport pandas as pd\n\n\nclass DataCollector(object):\n    '''\n    Class for collecting data generated by a Mesa model.\n\n    A DataCollector is instantiated with dictionaries of names of model- and\n    agent-level variables to collect, associated with functions which actually\n    collect them. When the collect(...) method is called, it executes these\n    functions one by one and stores the results.\n    '''\n    model_reporters = {}\n    agent_reporters = {}\n\n    model_vars = {}\n    agent_vars = {}\n    tables = {}\n\n    model = None\n\n    def __init__(self, model_reporters={}, agent_reporters={}, tables={}):\n        '''\n        Instantiate a DataCollector with lists of model and agent reporters.\n\n        Both model_reporters and agent_reporters accept a dictionary mapping a\n        variable name to a method used to collect it.\n        For example, if there was only one model-level reporter for number of\n        agents, it might look like:\n            {\"agent_count\": lambda m: m.schedule.get_agent_count() }\n        If there was only one agent-level reporter (e.g. the agent's energy),\n        it might look like this:\n            {\"energy\": lambda a: a.energy}\n\n        The tables arg accepts a dictionary mapping names of tables to lists of\n        columns. For example, if we want to allow agents to write their age\n        when they are destroyed (to keep track of lifespans), it might look\n        like:\n            {\"Lifespan\": [\"unique_id\", \"age\"]}\n\n        Args:\n            model_reporters: Dictionary of reporter names and functions.\n            agent_reporters: Dictionary of reporter names and functions.\n        '''\n\n        self.model_reporters = {}\n        self.agent_reporters = {}\n        self.tables = {}\n\n        for name, func in model_reporters.items():\n            self._new_model_reporter(name, func)\n\n        for name, func in agent_reporters.items():\n            self._new_agent_reporter(name, func)\n\n        for name, columns in tables.items():\n            self._new_table(name, columns)\n\n    def _new_model_reporter(self, reporter_name, reporter_function):\n        '''\n        Add a new model-level reporter to collect.\n        Args:\n            reporter_name: Name of the model-level variable to collect.\n            reporter_function: Function object that returns the variable when\n                               given a model instance.\n        '''\n\n        self.model_reporters[reporter_name] = reporter_function\n        self.model_vars[reporter_name] = []\n\n    def _new_agent_reporter(self, reporter_name, reporter_function):\n        '''\n        Add a new agent-level reporter to collect.\n        Args:\n            reporter_name: Name of the agent-level variable to collect.\n            reporter_function: Function object that returns the variable when\n                               given an agent object.\n        '''\n        self.agent_reporters[reporter_name] = reporter_function\n        self.agent_vars[reporter_name] = []\n\n    def _new_table(self, table_name, table_columns):\n        '''\n        Add a new table that objects can write to.\n        Args:\n            table_name: Name of the new table.\n            table_columns: List of columns to add to the table.\n        '''\n        new_table = {column: [] for column in table_columns}\n        self.tables[table_name] = new_table\n\n    def collect(self, model):\n        '''\n        Collect all the data for the given model object.\n        '''\n        if self.model_reporters:\n            for var, reporter in self.model_reporters.items():\n                self.model_vars[var].append(reporter(model))\n\n        if self.agent_reporters:\n            for var, reporter in self.agent_reporters.items():\n                agent_records = []\n                for agent in model.schedule.agents:\n                    agent_records.append((agent.unique_id, reporter(agent)))\n                self.agent_vars[var].append(agent_records)\n\n    def add_table_row(self, table_name, row, ignore_missing=False):\n        '''\n        Add a row dictionary to a specific table.\n\n        Args:\n            table_name: Name of the table to append a row to.\n            row: A dictionary of the form {column_name: value...}\n            ignore_missing: If True, fill any missing columns with Nones;\n                            if False, throw an error if any columns are missing\n        '''\n        if table_name not in self.tables:\n            raise Exception(\"Table does not exist.\")\n\n        for column in self.tables[table_name]:\n            if column in row:\n                self.tables[table_name][column].append(row[column])\n            elif ignore_missing:\n                self.tables[table_name][column].append(None)\n            else:\n                raise Exception(\"Could not insert row with missing column\")\n\n    def get_model_vars_dataframe(self):\n        '''\n        Create a pandas DataFrame from the model variables.\n        The DataFrame has one column for each model variable, and the index is\n        (implicitly) the model tick.\n        '''\n        return pd.DataFrame(self.model_vars)\n\n    def get_agent_vars_dataframe(self):\n        '''\n        Create a pandas DataFrame from the agent variables.\n        The DataFrame has one column for each variable, with two additional\n        columns for tick and agent_id.\n        '''\n\n        data = defaultdict(dict)\n        for var, records in self.agent_vars.items():\n            for step, entries in enumerate(records):\n                for entry in entries:\n                    agent_id = entry[0]\n                    val = entry[1]\n                    data[(step, agent_id)][var] = val\n        df = pd.DataFrame.from_dict(data, orient=\"index\")\n        df.index.names = [\"Step\", \"AgentID\"]\n        return df\n\n    def get_table_dataframe(self, table_name):\n        '''\n        Create a pandas DataFrame from a particular table.\n\n        Args:\n            table_name: The name of the table to convert.\n        '''\n        if table_name not in self.tables:\n            raise Exception(\"No such table.\")\n        return pd.DataFrame(self.tables[table_name])\n", "path": "mesa/datacollection.py"}], "after_files": [{"content": "'''\nMesa Data Collection Module\n=====================================================\n\nDataCollector is meant to provide a simple, standard way to collect data\ngenerated by a Mesa model. It collects three types of data: model-level data,\nagent-level data, and tables.\n\nA DataCollector is instantiated with two dictionaries of reporter names and\nassociated functions for each, one for model-level data and one for\nagent-level data; a third dictionary provides table names and columns.\n\nWhen the collect() method is called, each model-level function is called, with\nthe model as the argument, and the results associated with the relevant\nvariable. Then the agent-level functions are called on each\nagent in the model scheduler.\n\nAdditionally, other objects can write directly to tables by passing in an\nappropriate dictionary object for a table row.\n\nThe DataCollector then stores the data it collects in dictionaries:\n    * model_vars maps each reporter to a list of its values\n    * agent_vars maps each reporter to a list of lists, where each nested list\n    stores (agent_id, value) pairs.\n    * tables maps each table to a dictionary, with each column as a key with a\n    list as its value.\n\nFinally, DataCollector can create a pandas DataFrame from each collection.\n\nThe default DataCollector here makes several assumptions:\n    * The model has a schedule object called 'schedule'\n    * The schedule has an agent list called agents\n    * For collecting agent-level variables, agents must have a unique_id\n'''\nfrom collections import defaultdict\nimport pandas as pd\n\n\nclass DataCollector(object):\n    '''\n    Class for collecting data generated by a Mesa model.\n\n    A DataCollector is instantiated with dictionaries of names of model- and\n    agent-level variables to collect, associated with functions which actually\n    collect them. When the collect(...) method is called, it executes these\n    functions one by one and stores the results.\n    '''\n    model_reporters = {}\n    agent_reporters = {}\n\n    model_vars = {}\n    agent_vars = {}\n    tables = {}\n\n    model = None\n\n    def __init__(self, model_reporters={}, agent_reporters={}, tables={}):\n        '''\n        Instantiate a DataCollector with lists of model and agent reporters.\n\n        Both model_reporters and agent_reporters accept a dictionary mapping a\n        variable name to a method used to collect it.\n        For example, if there was only one model-level reporter for number of\n        agents, it might look like:\n            {\"agent_count\": lambda m: m.schedule.get_agent_count() }\n        If there was only one agent-level reporter (e.g. the agent's energy),\n        it might look like this:\n            {\"energy\": lambda a: a.energy}\n\n        The tables arg accepts a dictionary mapping names of tables to lists of\n        columns. For example, if we want to allow agents to write their age\n        when they are destroyed (to keep track of lifespans), it might look\n        like:\n            {\"Lifespan\": [\"unique_id\", \"age\"]}\n\n        Args:\n            model_reporters: Dictionary of reporter names and functions.\n            agent_reporters: Dictionary of reporter names and functions.\n        '''\n\n        self.model_reporters = {}\n        self.agent_reporters = {}\n\n        self.model_vars = {}\n        self.agent_vars = {}\n        self.tables = {}\n\n        for name, func in model_reporters.items():\n            self._new_model_reporter(name, func)\n\n        for name, func in agent_reporters.items():\n            self._new_agent_reporter(name, func)\n\n        for name, columns in tables.items():\n            self._new_table(name, columns)\n\n    def _new_model_reporter(self, reporter_name, reporter_function):\n        '''\n        Add a new model-level reporter to collect.\n        Args:\n            reporter_name: Name of the model-level variable to collect.\n            reporter_function: Function object that returns the variable when\n                               given a model instance.\n        '''\n\n        self.model_reporters[reporter_name] = reporter_function\n        self.model_vars[reporter_name] = []\n\n    def _new_agent_reporter(self, reporter_name, reporter_function):\n        '''\n        Add a new agent-level reporter to collect.\n        Args:\n            reporter_name: Name of the agent-level variable to collect.\n            reporter_function: Function object that returns the variable when\n                               given an agent object.\n        '''\n        self.agent_reporters[reporter_name] = reporter_function\n        self.agent_vars[reporter_name] = []\n\n    def _new_table(self, table_name, table_columns):\n        '''\n        Add a new table that objects can write to.\n        Args:\n            table_name: Name of the new table.\n            table_columns: List of columns to add to the table.\n        '''\n        new_table = {column: [] for column in table_columns}\n        self.tables[table_name] = new_table\n\n    def collect(self, model):\n        '''\n        Collect all the data for the given model object.\n        '''\n        if self.model_reporters:\n            for var, reporter in self.model_reporters.items():\n                self.model_vars[var].append(reporter(model))\n\n        if self.agent_reporters:\n            for var, reporter in self.agent_reporters.items():\n                agent_records = []\n                for agent in model.schedule.agents:\n                    agent_records.append((agent.unique_id, reporter(agent)))\n                self.agent_vars[var].append(agent_records)\n\n    def add_table_row(self, table_name, row, ignore_missing=False):\n        '''\n        Add a row dictionary to a specific table.\n\n        Args:\n            table_name: Name of the table to append a row to.\n            row: A dictionary of the form {column_name: value...}\n            ignore_missing: If True, fill any missing columns with Nones;\n                            if False, throw an error if any columns are missing\n        '''\n        if table_name not in self.tables:\n            raise Exception(\"Table does not exist.\")\n\n        for column in self.tables[table_name]:\n            if column in row:\n                self.tables[table_name][column].append(row[column])\n            elif ignore_missing:\n                self.tables[table_name][column].append(None)\n            else:\n                raise Exception(\"Could not insert row with missing column\")\n\n    def get_model_vars_dataframe(self):\n        '''\n        Create a pandas DataFrame from the model variables.\n        The DataFrame has one column for each model variable, and the index is\n        (implicitly) the model tick.\n        '''\n        return pd.DataFrame(self.model_vars)\n\n    def get_agent_vars_dataframe(self):\n        '''\n        Create a pandas DataFrame from the agent variables.\n        The DataFrame has one column for each variable, with two additional\n        columns for tick and agent_id.\n        '''\n\n        data = defaultdict(dict)\n        for var, records in self.agent_vars.items():\n            for step, entries in enumerate(records):\n                for entry in entries:\n                    agent_id = entry[0]\n                    val = entry[1]\n                    data[(step, agent_id)][var] = val\n        df = pd.DataFrame.from_dict(data, orient=\"index\")\n        df.index.names = [\"Step\", \"AgentID\"]\n        return df\n\n    def get_table_dataframe(self, table_name):\n        '''\n        Create a pandas DataFrame from a particular table.\n\n        Args:\n            table_name: The name of the table to convert.\n        '''\n        if table_name not in self.tables:\n            raise Exception(\"No such table.\")\n        return pd.DataFrame(self.tables[table_name])\n", "path": "mesa/datacollection.py"}]}