python - 将结构化数据附加到 Python 中的类属性
问题描述
我有几个用于运行数值模拟的对象。下面显示了一个最小示例,其中有两个对象: 1) 一个Environment
对象具有两种状态(x 和 y),它通过时间随机模拟;2)Simulation
管理模拟并在整个模拟过程中保存环境状态的对象。
在 Simulation 对象中,我想保存 Environment 的状态 1) 通过时间和 2) 在多个模拟中。随着时间的推移,我可以使用 defaultdict 在单个模拟中保存状态变量,但在模拟中,我不清楚保存已生成的 defaultdict 的最佳方法。如果我附加到一个列表(不使用副本),那么由于列表的可变性,该列表将返回所有相同的默认字典。在下面的示例中,我使用,正如这里copy.copy
的答案所暗示的那样。
是否有更“Pythonic”的方法?使用不可变类型来存储每个模拟的默认字典会更好吗?
import copy
from collections import defaultdict
import numpy as np, pandas as pd
from matplotlib import pyplot as plt
class Environment(object):
"""
Class representing a random walk of two variables x and y
Methods
-------
start_simulation: draw values from state variables from priors
step: add random noise to state variables
current_state: return current state of x and y in a dict
"""
def __init__(self, mu1, sigma1, mu2, sigma2):
self.mu1 = mu1
self.mu2 = mu2
self.sigma1 = sigma1
self.sigma2 = sigma2
def start_simulation(self):
self.x = self.mu1 + self.sigma1 * np.random.randn()
self.y = self.mu2 + self.sigma2 * np.random.randn()
def step(self):
self.x += self.sigma1 * np.random.randn()
self.y += self.sigma2 * np.random.randn()
def current_state(self):
return({"x": self.x, "y": self.y})
class Simulation(object):
"""
Class representing a simulation object for handling the Environment object
and storing data
Methods
-------
start_simulation: start the simulation; initialise state of the environment
simulate: generate n_simulations simulations of n_timesteps time steps each
save_state:
"""
def __init__(self, env, n_timesteps):
self.env = env
self.n_timesteps = n_timesteps
self.data_all = []
self.data_states = defaultdict(list)
def start_simulation(self):
self.timestep = 0
self.env.start_simulation()
# Append current data (if non empty)
if self.data_states:
self.data_all.append(copy.copy(self.data_states)) # <---------- this step
# without copy.copy this will return all elements of the list data_all to be the
# same default dict at the end of all simulations - lists are mutable
# Reset data_current
self.data_states = defaultdict(list)
def simulate(self, n_simulations):
"""
Run simulation for n_simulations and n_timesteps timesteps
"""
self.start_simulation()
for self.simulation in range(n_simulations):
self.timestep = 0
while(self.timestep < self.n_timesteps):
self.env.step()
self.save_state(self.env.current_state())
self.timestep += 1
self.start_simulation()
def save_state(self, state):
"""
Save results to a default dict
"""
for key, value in state.items():
self.data_states[key].append(value)
if __name__ == "__main__":
# Run 7 simulations, each for for 20 time steps
N_TIME = 20
N_SIM = 7
e = Environment(
mu1 = 1.4, sigma1 = 0.1,
mu2 = 2.6, sigma2 = 0.05)
s = Simulation(env = e, n_timesteps = N_TIME)
s.simulate(N_SIM)
# Plot output
fig, ax = plt.subplots()
for var, c in zip(["x", "y"], ["#D55E00", "#009E73"]):
[ax.plot(pd.DataFrame(d)[var], label = var, color = c) for d in s.data_all]
ax.set_xlabel("Time")
ax.set_ylabel("Value")
plt.show()
解决方案
推荐阅读
- javascript - 如何使用 offsetWidth 和 offsetLeft 将 div 动态居中于另一个 div
- amazon-web-services - Amazon Kinesis 在分片重新缩放后复制数据
- python - 带有fabric2的conda虚拟环境
- mysql - 基于 CSV 文件自动生成 MySQL 模式
- java - 无法在 videogular 中播放使用亚马逊弹性转码器创建的 mpegdash 视频
- python - Pandas subset randomly selected number of rows from dataframe based on values in another data
- python - 如何解决 Multiprocessing.Pool 问题?
- kotlin - kotlinx.coroutines 基本示例无法识别 GlobalScope.launch 提供的 CoroutineScope
- node.js - 我如何对刚刚返回的 else 语句进行单元测试。- Nodejs,诗乃
- sql - 动态选择列名