This repository has been archived by the owner on Oct 26, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmemory.py
229 lines (165 loc) · 6 KB
/
memory.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
import pandas as pd
class MemoryItemBase(object):
def __init__(self, size):
self.size = size
@property
def size(self):
return self._size
@size.setter
def size(self, s):
if not isinstance(s, int):
raise TypeError("Memory size must be an int")
if s < 1:
raise ValueError("Memory size must be greater than 1")
self._size = s
def count(self):
return NotImplementedError
def store(self, item):
raise NotImplementedError
def fetch_last(self, key):
raise NotImplementedError
class ListItem(MemoryItemBase):
def __init__(self, size):
MemoryItemBase.__init__(self, size)
self.items = []
def store(self, item):
self.items.append(item)
if len(self.items) > self.size:
self.items = self.items[-self.size:]
def fetch_last(self, i):
return self.items[-i:]
def count(self):
return len(self.items)
class MemoryBase(object):
def __init__(self, size=100, columns=None):
self.size = size
if columns is not None:
self.new(columns)
def new(self, name):
"""
Adds new columns to memory
Parameters:
string or list of strings
"""
raise NotImplementedError
def store(self, d):
"""
Takes in a dictionary or list of dictionaries and adds to memory
"""
raise NotImplementedError
def fetch_last(self, i, name=None, return_type="dict"):
"""
Returns last i rows for column if name, else table
return_type:
"dict" - Dictionary
"numpy" - Numpy array (values only)
"pandas" - Pandas DataFrame
"""
raise NotImplementedError
def count(self, name=None):
"""
If name is a string returns count stored for that column
Else returns max stored columns
"""
raise NotImplementedError
def update(self, d):
"""
Takes in dictionary and updates most recent entry
"""
raise NotImplementedError
def export(self):
raise NotImplementedError
class ListMemory(MemoryBase):
def __init__(self, size=100, columns=None):
self.items = {} # Must go before Base init as Base may call it
MemoryBase.__init__(self, size, columns)
def new(self, name):
if isinstance(name, str):
self.items[name] = ListItem(size=self.size)
else:
for n in name:
self.items[n] = ListItem(size=self.size)
def store(self, d):
if isinstance(d, dict):
for key, value in d.iteritems():
self.items[key].store(value)
mem_keys = [key for key in self.items.keys() if key not in d.keys()]
for mem_key in mem_keys:
self.items[mem_key].store(None)
else:
for m in d:
for key, value in m.iteritems():
self.items[key].store(value)
mem_keys = [key for key in self.items.keys() if key not in m.keys()]
for mem_key in mem_keys:
self.items[mem_key].store(None)
def fetch_last(self, i, name=None, return_type="dict"):
if return_type not in ["dict"]:
raise TypeError("Return type not currently supported")
if name is not None:
return self.items[name].fetch_last(i)
else:
ret_dict = {}
for key in self.items.keys():
ret_dict[key] = self.items[key].fetch_last(i)
return ret_dict
def count(self, name=None):
if name is not None:
return self.items[name].count()
else:
return max([self.items[key].count() for key in self.items.keys()])
def update(self, d):
for key, value in d.iteritems():
self.items[key].items[-1] = value
def export(self):
return {"Type": "List Memory",
"Size": self.size,
"Columns": self.items.keys()}
class PandasMemory(MemoryBase):
def __init__(self, size=100, columns=None):
self.df = pd.DataFrame() # Has to go before base init as based may call it
MemoryBase.__init__(self, size, columns)
def new(self, name):
if isinstance(name, str):
self.df[name] = None
else:
for n in name:
self.df[n] = None
def store(self, d):
if isinstance(d, dict):
self.df = self.df.append(d, ignore_index=True)
else:
for m in d:
self.df = self.df.append(m, ignore_index=True)
def fetch_last(self, i, name=None, return_type="pandas"):
if return_type not in ["pandas"]:
raise TypeError("Return type not currently supported")
if return_type == "pandas":
ret_df = self.df.ix[-i:, name] if name is not None else self.df.iloc[-i:]
ret_df.reset_index(drop=True, inplace=True)
return ret_df
# Returns entire history for last i episodes
def fetch_episode(self, i, name="done", return_type="pandas"):
if return_type not in ["pandas"]:
raise TypeError("Return type not currently supported")
if return_type == "pandas":
ep_starts = ([0] + self.df[self.df[name]].index.tolist())[::-1]
if self.count()-1 in ep_starts:
ep_starts.remove(self.count()-1)
if len(ep_starts) < i:
return None
start = ep_starts[i-1]
return self.df.iloc[start+1:]
def count(self, name=None):
if name is not None:
return self.df[name].count()
else:
return len(self.df.index)
def update(self, d):
curr_index = self.count()
for key, value in d.iteritems():
self.df.set_value(curr_index-1, key, value)
def export(self):
return {"Type": "Pandas",
"Size": self.size,
"Columns": self.df.columns()}