如何生成具有内部行和列依赖关系的复杂假设数据框架?



是否有一种优雅的方式使用hypothesis直接生成复杂的pandas数据帧与内部行和列依赖关系?假设我想要这样的列:

[longitude][latitude][some-text-meta][some-numeric-meta][numeric-data][some-junk][numeric-data][…

地理坐标可以单独随机选择,但集合通常必须来自一般区域(例如,如果你在地球的两端有两个点,标准的重新投影就不起作用)。通过选择带有一种策略的区域以及该区域内带有另一种策略的坐标列,可以很容易地处理这一问题。到目前为止一切顺利……

@st.composite
def plaus_spamspam_arrs(
draw,
st_lonlat=plaus_lonlat_arr,
st_values=plaus_val_arr,
st_areas=plaus_area_arr,
st_meta=plaus_meta_arr,
bounds=ARR_LEN,
):
"""Returns plausible spamspamspam arrays"""
size = draw(st.integers(*bounds))
coords = draw(st_lonlat(size=size))
values = draw(st_values(size=size))
areas = draw(st_areas(size=size))
meta = draw(st_meta(size=size))
return PlausibleData(coords, values, areas, meta)
上面的代码片段为协调的单值数据创建了干净的numpy数组。但是列示例中的数字数据(n列中散布着垃圾)也可能具有逐行依赖关系,例如需要规范化到涉及逐行求和的某些因素和/或在运行时动态选择的其他因素。

我可以单独生成所有这些位,但是我看不出如何在不使用笨拙的基于连接的技术的情况下将它们缝合到单个数据帧中,我认为这会破坏基于draw的收缩。此外,我需要一个超越上面的解决方案,所以黑客可能会让我走得太远……

也许builds有什么问题?我只是不太明白该怎么做。谢谢分享,如果你知道!一个简短的例子作为灵感就足够了。

更新我可以大致如下生成列:

@st.composite
def plaus_df_inputs(
draw, *, nrows=None, ncols=None, nrow_bounds=ARR_LEN, ncol_bounds=COL_LEN
):
"""Returns …"""
box_lon, box_lat = draw(plaus_box_geo())
ncols_jnk = draw(st.integers(*ncol_bounds)) if ncols is None else ncols
ncols_val = draw(st.integers(*ncol_bounds)) if ncols is None else ncols
keys_val = draw(plaus_smp_key_elm(size=ncols_val))
nrows = draw(st.integers(*nrow_bounds)) if nrows is None else nrows
cols = (
plaus_df_cols_lonlat(lons=plaus_lon(box_lon), lats=plaus_lat(box_lat))
+ plaus_df_cols_meta()
+ plaus_df_cols_value(keys=keys_val)
+ draw(plaus_df_cols_junk(size=ncols_jnk))
)
random.shuffle(cols)
return draw(st_pd.data_frames(cols, index=plaus_df_idx(size=nrows)))

子统计是像

这样的东西
@st.composite
def plaus_df_cols_junk(
draw, *, size=1, names=plaus_meta(), dtypes=plaus_dtype(), unique=False
):
"""Returns strategy for list of columns of plausible junk data."""
result = set()
for _ in range(size):
result.add(draw(names.filter(lambda name: name not in result)))
return [
st_pd.column(name=result.pop(), dtype=draw(dtypes), unique=unique)
for _ in range(size)
]

我需要的是一些更优雅的东西,它包含了基于行的依赖关系。

from hypothesis import strategies as st
@st.composite
def interval_sets(draw):
# To create our interval sets, we'll draw from a strategy that shrinks well,
# and then transform it into the format we want.  More specifically, we'll use
# a single lists() strategy so that the shrinker can delete chunks atomically,
# and then rearrange the floats that we draw as part of this.
base_elems = st.tuples(
# Different floats bounds to ensure we get at least one valid start and end.
st.text(),
st.floats(0, 1, exclude_max=True),
st.floats(0, 1, exclude_min=True),
)
base = draw(st.lists(base_elems, min_size=1, unique_by=lambda t: t[0]))
nums = sorted(sum((t[1:] for t in base), start=()))  # arrange our endpoints
return [
{"name": name, "start": start, "end": end, "size": end - start}
for (name, _, _), start, end in zip(base, nums[::2], nums[1::2])
]

最新更新