Skip to content

Instantly share code, notes, and snippets.

@a-recknagel
Last active September 22, 2023 09:28
Show Gist options
  • Save a-recknagel/e7bc969512853866becb8bc90cc093d7 to your computer and use it in GitHub Desktop.
Save a-recknagel/e7bc969512853866becb8bc90cc093d7 to your computer and use it in GitHub Desktop.
csv imploder w/ example
from pathlib import Path
from csv import DictReader
from collections import defaultdict
class DupelessDict(dict):
"""Duplicate entries may not pass silently."""
def __setitem__(self, key, value):
if key in self:
raise ValueError(f"Duplicate {key=} encountered.")
super().__setitem__(key, value)
def csv_to_nested_dict(path: Path, nesting_keys: list[str], result_keys: list[str]) -> dict:
"""Implodes a csv into a dictionary.
The resulting format of the dictionary can be consumed as-is by a pydantic class
representing the nested/imploded format.
Example:
On a csv with the columns a,b,c and d, assuming that a and b are nesting keys,
and d and e are the result keys, the resulting structure given the sample
a,b,c,d,e
1,2,3,10,5
1,3,3,20,5
2,2,4,30,5
2,3,4,30,4
would be
{
"a": {
"1": {
"b": {
"2": { "d": "10", "e": "5" },
"3": { "d": "20", "e": "5" }
}
},
"2": {
"b": {
"2": { "d": "30", "e": "5" },
"3": { "d": "30", "e": "4" }
}
}
}
}
Which is represented by the following pydantic class structure
class TopLevel(pydantic.BaseModel):
a: dict[int, B]
class B(pydantic.BaseModel):
b: dict[int, Result]
class Result(pydantic.BaseModel):
d: int
e: int
Notes:
- keys that don't get mentioned as either nesting key or result key get ignored
- all values are parsed as strings
- duplicate nesting key sets in the csv lead to an error, e.g. if the csv in the
example had another line ` 2,3,5,40,6`; because a and b are the sole nesting keys
and a=2 and b=3 had already been seen, the csv file is ambiguous and needs to
be fixed.
"""
try:
*keys, last_key = nesting_keys
except ValueError:
print("error", "Need keys in order to generate nesting levels.")
raise
# apply level of nesting to initialise a pydantic-consumable nested dictionary
ret_code = f'{{"{last_key}": DupelessDict()}}'
for key in reversed(keys):
ret_code = f'{{"{key}": defaultdict(lambda: {ret_code})}}'
print("debug", ret_code)
ret = eval(ret_code, dict(defaultdict=defaultdict, DupelessDict=DupelessDict))
# parse file
with open(path) as csv_file:
for idx, row in enumerate(DictReader(csv_file)):
cur = ret
for key in keys:
cur = cur[key][row[key]]
try:
cur[last_key][row[last_key]] = {k: row[k] for k in result_keys}
except ValueError:
print("error", f"Got duplicate entry in row #{idx} with content {row}.")
raise
return ret
"""Pydantic class structures, given the shape of the csv at hand."""
from __future__ import annotations
from pathlib import Path
from typing import TypeAlias, Literal
from decimal import Decimal
import pydantic
FooValues: TypeAlias = Literal[1, 2, 3, 4, 5, 6, 7, 8]
BazValues: TypeAlias = Literal[12, 24, 36, 48, 60, 72, 84]
QuxValues: TypeAlias = Literal["New", "Old", "Repeat"]
BAR_LIMIT_MIN = 10
BAR_LIMIT_MAX = 100
class Nested(pydantic.BaseModel):
"""Toplevel."""
foo: dict[FooValues, Bar]
@pydantic.field_validator("foo", mode="before")
def coerce_to_int(cls, v):
return {int(key): value for key, value in v.items()}
class Bar(pydantic.BaseModel):
"""Maps its key to a range through the accessor `get_bar_range`.
The `bar` field itself should not be read directly.
"""
bar: dict[tuple[int, int], Baz]
def get_bar_range(self, key: int):
for (min, max), v in self.bar.items():
if min < key <= max:
return v
raise ValueError(
f"{key=} is out of bounds, please stick to the limits between "
f"{BAR_LIMIT_MIN=} and {BAR_LIMIT_MAX=}."
)
@pydantic.field_validator("bar", mode="before")
def coerce_to_int_tuple(cls, v):
split = lambda x: tuple(map(int, (x.split("-", 1)))) if isinstance(x, str) else x
return {split(key): value for key, value in v.items()}
@pydantic.field_validator("bar", mode="after")
def no_gaps_and_no_overlap(cls, v):
keys = sorted(v.keys())
if not keys:
raise ValueError("At least one boundary needs to be set.")
min_min, max_max = keys[0][0], keys[-1][1]
if min_min != BAR_LIMIT_MIN:
raise ValueError(
f"Lowest value {keys[0][0]} doesn't match {BAR_LIMIT_MIN=}."
)
if max_max != BAR_LIMIT_MAX:
raise ValueError(
f"Highest value {keys[-1][1]} doesn't match {BAR_LIMIT_MAX=}."
)
last = keys[0][1]
for min, max in keys[1:]:
if last != min:
raise ValueError(f"Got a gap between {last=} and {min=}.")
last = max
return v
class Baz(pydantic.BaseModel):
"""Yet another nesting level."""
baz: dict[BazValues, Qux]
@pydantic.field_validator("baz", mode="before")
def coerce_to_int(cls, v):
return {int(key): value for key, value in v.items()}
class Qux(pydantic.BaseModel):
"""And the final nesting, which maps to the actual entries."""
qux: dict[QuxValues, Result]
class Result(pydantic.BaseModel):
"""The result we're looking for."""
a: int
b: Decimal
c: Literal["strategy_1", "strategy_2", "strategy_3"]
Nested.model_rebuild()
foo bar baz qux a b c
1 10-30 12 New 0 0.4266724448924709 strategy_1
1 10-30 12 Old 3 0.9527535060171675 strategy_3
1 10-30 12 Repeat 3 0.546172410319005 strategy_3
1 10-30 24 New 0 0.34270197832762583 strategy_2
1 10-30 24 Old 1 0.872233130556178 strategy_2
1 10-30 24 Repeat 2 0.9632045153317987 strategy_3
1 10-30 36 New 1 0.5502551776799455 strategy_1
1 10-30 36 Old 0 0.24024468254119902 strategy_1
1 10-30 36 Repeat 3 0.892669553468528 strategy_3
1 10-30 48 New 2 0.6776063145131122 strategy_2
1 10-30 48 Old 1 0.48012115486562823 strategy_2
1 10-30 48 Repeat 0 0.8246811750503875 strategy_2
1 10-30 60 New 0 0.4903378439781051 strategy_1
1 10-30 60 Old 2 0.8934814603721083 strategy_2
1 10-30 60 Repeat 3 0.9388716771569701 strategy_3
1 10-30 72 New 1 0.8307917155448303 strategy_1
1 10-30 72 Old 1 0.8660765466658492 strategy_2
1 10-30 72 Repeat 1 0.06081954603145845 strategy_3
1 10-30 84 New 0 0.17994245860713254 strategy_1
1 10-30 84 Old 2 0.5131799754097571 strategy_1
1 10-30 84 Repeat 1 0.9471103071160246 strategy_1
1 30-35 12 New 1 0.5533558416507942 strategy_2
1 30-35 12 Old 0 0.7697953128665532 strategy_3
1 30-35 12 Repeat 2 0.1503691460092258 strategy_1
1 30-35 24 New 1 0.3472317242121141 strategy_3
1 30-35 24 Old 2 0.03536443578397663 strategy_1
1 30-35 24 Repeat 2 0.6106823706236627 strategy_3
1 30-35 36 New 2 0.5076423932104247 strategy_1
1 30-35 36 Old 1 0.20029621890649774 strategy_2
1 30-35 36 Repeat 3 0.6255840846959848 strategy_3
1 30-35 48 New 3 0.3669919113324769 strategy_2
1 30-35 48 Old 2 0.0286973383117628 strategy_2
1 30-35 48 Repeat 2 0.26467206646098596 strategy_3
1 30-35 60 New 1 0.46588997329770865 strategy_1
1 30-35 60 Old 1 0.5893487986061441 strategy_1
1 30-35 60 Repeat 2 0.4023001198634414 strategy_2
1 30-35 72 New 1 0.7750202935549937 strategy_3
1 30-35 72 Old 1 0.288477237090749 strategy_2
1 30-35 72 Repeat 3 0.5248224121125081 strategy_1
1 30-35 84 New 0 0.13629742301471537 strategy_1
1 30-35 84 Old 1 0.26185688945833707 strategy_3
1 30-35 84 Repeat 2 0.9896913763596721 strategy_1
1 35-50 12 New 2 0.24350238819347836 strategy_3
1 35-50 12 Old 2 0.5078100087318244 strategy_3
1 35-50 12 Repeat 1 0.17793181707987316 strategy_2
1 35-50 24 New 1 0.887812501822644 strategy_1
1 35-50 24 Old 3 0.9075921784810266 strategy_1
1 35-50 24 Repeat 1 0.7720322677540631 strategy_2
1 35-50 36 New 2 0.5160019288839062 strategy_2
1 35-50 36 Old 1 0.8103403682303163 strategy_2
1 35-50 36 Repeat 0 0.5934231594921536 strategy_2
1 35-50 48 New 0 0.6858099742591788 strategy_2
1 35-50 48 Old 1 0.41210732948580364 strategy_1
1 35-50 48 Repeat 3 0.9533624040850617 strategy_2
1 35-50 60 New 2 0.45525353252589074 strategy_3
1 35-50 60 Old 2 0.7844389606197337 strategy_3
1 35-50 60 Repeat 2 0.14503943683324572 strategy_2
1 35-50 72 New 1 0.32843971557711726 strategy_1
1 35-50 72 Old 2 0.7686222847481141 strategy_2
1 35-50 72 Repeat 3 0.8705675426266423 strategy_3
1 35-50 84 New 1 0.3142136944747511 strategy_2
1 35-50 84 Old 0 0.16614971029882686 strategy_3
1 35-50 84 Repeat 3 0.12286860270918698 strategy_1
1 50-60 12 New 0 0.4719648145804416 strategy_3
1 50-60 12 Old 2 0.5310476897291312 strategy_3
1 50-60 12 Repeat 1 0.1391262909459242 strategy_3
1 50-60 24 New 1 0.94587101767926 strategy_3
1 50-60 24 Old 1 0.17518264747737367 strategy_1
1 50-60 24 Repeat 2 0.01968808738059402 strategy_1
1 50-60 36 New 3 0.4146674268605739 strategy_2
1 50-60 36 Old 1 0.8307444529779199 strategy_2
1 50-60 36 Repeat 2 0.3279286665243093 strategy_3
1 50-60 48 New 3 0.4983760404736044 strategy_3
1 50-60 48 Old 3 0.027978539807280156 strategy_3
1 50-60 48 Repeat 3 0.8494458699648273 strategy_3
1 50-60 60 New 2 0.19987144537970325 strategy_3
1 50-60 60 Old 0 0.819891029940107 strategy_3
1 50-60 60 Repeat 1 0.4326101740114865 strategy_3
1 50-60 72 New 1 0.3828380942452667 strategy_3
1 50-60 72 Old 2 0.5689450863189397 strategy_2
1 50-60 72 Repeat 3 0.8313474729021397 strategy_3
1 50-60 84 New 0 0.5870043948171478 strategy_1
1 50-60 84 Old 2 0.07912363542332002 strategy_3
1 50-60 84 Repeat 0 0.4917493474100526 strategy_2
1 60-90 12 New 0 0.8662460788176378 strategy_1
1 60-90 12 Old 3 0.784589448486164 strategy_1
1 60-90 12 Repeat 3 0.6986859300394891 strategy_2
1 60-90 24 New 0 0.7340977959048232 strategy_1
1 60-90 24 Old 0 0.26481905416298246 strategy_2
1 60-90 24 Repeat 2 0.5673892348659945 strategy_3
1 60-90 36 New 1 0.8884148754933351 strategy_3
1 60-90 36 Old 2 0.9794882390601818 strategy_1
1 60-90 36 Repeat 0 0.06390542353394457 strategy_2
1 60-90 48 New 3 0.93644551381388 strategy_2
1 60-90 48 Old 0 0.10301792115516561 strategy_3
1 60-90 48 Repeat 0 0.10938253139264043 strategy_2
1 60-90 60 New 2 0.7070161153552462 strategy_3
1 60-90 60 Old 2 0.7209391893420465 strategy_1
1 60-90 60 Repeat 3 0.8189650286762961 strategy_2
1 60-90 72 New 2 0.2355003692904144 strategy_1
1 60-90 72 Old 1 0.4475267976625351 strategy_1
1 60-90 72 Repeat 3 0.08199078489583012 strategy_2
1 60-90 84 New 2 0.4537791649520474 strategy_2
1 60-90 84 Old 2 0.6029263436803897 strategy_1
1 60-90 84 Repeat 0 0.14063022624907617 strategy_1
1 90-100 12 New 3 0.7553994327189378 strategy_3
1 90-100 12 Old 0 0.3443151947722034 strategy_2
1 90-100 12 Repeat 1 0.7826238789082501 strategy_2
1 90-100 24 New 1 0.4605955461010244 strategy_3
1 90-100 24 Old 0 0.7039555842473046 strategy_1
1 90-100 24 Repeat 3 0.41839124409717965 strategy_3
1 90-100 36 New 3 0.11220536450881857 strategy_2
1 90-100 36 Old 3 0.30195426644201195 strategy_3
1 90-100 36 Repeat 1 0.7482844299006747 strategy_3
1 90-100 48 New 1 0.42629977617139925 strategy_1
1 90-100 48 Old 1 0.5952406060806115 strategy_2
1 90-100 48 Repeat 2 0.9779454380041024 strategy_1
1 90-100 60 New 1 0.8028178166614995 strategy_1
1 90-100 60 Old 3 0.6215110350427873 strategy_2
1 90-100 60 Repeat 0 0.8450227801311428 strategy_1
1 90-100 72 New 3 0.46296624623055527 strategy_3
1 90-100 72 Old 1 0.7095884844087631 strategy_3
1 90-100 72 Repeat 3 0.757017466366116 strategy_2
1 90-100 84 New 0 0.23260152747648866 strategy_1
1 90-100 84 Old 0 0.8388370568019123 strategy_3
1 90-100 84 Repeat 3 0.5501939331450025 strategy_2
2 10-30 12 New 3 0.4372012015662735 strategy_1
2 10-30 12 Old 0 0.7071378092168606 strategy_2
2 10-30 12 Repeat 0 0.6783518173941177 strategy_1
2 10-30 24 New 1 0.46678580598360875 strategy_2
2 10-30 24 Old 2 0.0987948721387577 strategy_2
2 10-30 24 Repeat 2 0.5824966106084735 strategy_1
2 10-30 36 New 2 0.42109050880136767 strategy_2
2 10-30 36 Old 0 0.8346611255622738 strategy_2
2 10-30 36 Repeat 2 0.8177777146116368 strategy_1
2 10-30 48 New 0 0.14459711095278482 strategy_1
2 10-30 48 Old 2 0.7244209805389498 strategy_2
2 10-30 48 Repeat 1 0.687522210277254 strategy_3
2 10-30 60 New 3 0.5207015907101213 strategy_1
2 10-30 60 Old 0 0.9238346969752951 strategy_1
2 10-30 60 Repeat 0 0.24447343613393968 strategy_2
2 10-30 72 New 0 0.07810137871684697 strategy_1
2 10-30 72 Old 2 0.20054472506044274 strategy_2
2 10-30 72 Repeat 3 0.358231285252259 strategy_3
2 10-30 84 New 2 0.44988346089395215 strategy_1
2 10-30 84 Old 3 0.130296503590838 strategy_2
2 10-30 84 Repeat 3 0.4051027160907479 strategy_3
2 30-35 12 New 0 0.7351117904529086 strategy_1
2 30-35 12 Old 2 0.3026494829679641 strategy_1
2 30-35 12 Repeat 2 0.020817997944073796 strategy_2
2 30-35 24 New 3 0.3089076448251662 strategy_3
2 30-35 24 Old 2 0.9779708314744219 strategy_1
2 30-35 24 Repeat 0 0.07908434957117638 strategy_1
2 30-35 36 New 3 0.43338104574132397 strategy_1
2 30-35 36 Old 3 0.7183189533261207 strategy_2
2 30-35 36 Repeat 0 0.6546131835904567 strategy_2
2 30-35 48 New 2 0.20825005193013468 strategy_1
2 30-35 48 Old 1 0.9389762285658946 strategy_1
2 30-35 48 Repeat 3 0.9167025245992748 strategy_2
2 30-35 60 New 0 0.6007751271354053 strategy_1
2 30-35 60 Old 0 0.9943613340305949 strategy_2
2 30-35 60 Repeat 3 0.23507076619005685 strategy_2
2 30-35 72 New 0 0.5023958227565437 strategy_1
2 30-35 72 Old 0 0.895043791021887 strategy_3
2 30-35 72 Repeat 0 0.5039616712914651 strategy_1
2 30-35 84 New 0 0.4770210256222166 strategy_2
2 30-35 84 Old 2 0.307244119303534 strategy_2
2 30-35 84 Repeat 0 0.23823639890894055 strategy_2
2 35-50 12 New 2 0.29877519723108603 strategy_3
2 35-50 12 Old 1 0.1777837932211307 strategy_3
2 35-50 12 Repeat 0 0.8933510485678792 strategy_1
2 35-50 24 New 1 0.392677228447184 strategy_3
2 35-50 24 Old 0 0.9151131323250142 strategy_3
2 35-50 24 Repeat 2 0.44995872708773865 strategy_2
2 35-50 36 New 0 0.05424882795675645 strategy_1
2 35-50 36 Old 3 0.5867640510919183 strategy_3
2 35-50 36 Repeat 1 0.20945748982807266 strategy_3
2 35-50 48 New 3 0.23431952017528535 strategy_3
2 35-50 48 Old 0 0.43934786626593003 strategy_3
2 35-50 48 Repeat 1 0.584843071686032 strategy_2
2 35-50 60 New 1 0.9571487464144182 strategy_3
2 35-50 60 Old 0 0.44878774867456983 strategy_3
2 35-50 60 Repeat 3 0.8210184952480016 strategy_1
2 35-50 72 New 0 0.28392743299702605 strategy_3
2 35-50 72 Old 1 0.23636863333893465 strategy_3
2 35-50 72 Repeat 1 0.9717404002066083 strategy_2
2 35-50 84 New 2 0.13770704952258728 strategy_3
2 35-50 84 Old 1 0.40930388692071895 strategy_2
2 35-50 84 Repeat 1 0.9803709219515709 strategy_2
2 50-60 12 New 2 0.20575275878125165 strategy_2
2 50-60 12 Old 1 0.4912754055333717 strategy_2
2 50-60 12 Repeat 2 0.6279109420276854 strategy_2
2 50-60 24 New 2 0.20252215462437217 strategy_3
2 50-60 24 Old 2 0.7309754149905157 strategy_1
2 50-60 24 Repeat 3 0.593276027727908 strategy_1
2 50-60 36 New 3 0.7884684573544009 strategy_1
2 50-60 36 Old 2 0.19554136333349337 strategy_1
2 50-60 36 Repeat 1 0.20410446954638917 strategy_1
2 50-60 48 New 1 0.8259344355929092 strategy_1
2 50-60 48 Old 0 0.06622740720278764 strategy_3
2 50-60 48 Repeat 2 0.7199470843425596 strategy_3
2 50-60 60 New 3 0.8643553150870694 strategy_2
2 50-60 60 Old 3 0.3274592371219155 strategy_3
2 50-60 60 Repeat 1 0.9617841165909763 strategy_1
2 50-60 72 New 1 0.7671443355335522 strategy_1
2 50-60 72 Old 0 0.7066680678775858 strategy_2
2 50-60 72 Repeat 0 0.7118267043227049 strategy_1
2 50-60 84 New 2 0.003867070992134236 strategy_1
2 50-60 84 Old 1 0.5303485160382712 strategy_2
2 50-60 84 Repeat 0 0.07893153865987501 strategy_1
2 60-90 12 New 1 0.34996937688223695 strategy_1
2 60-90 12 Old 3 0.9129382987797086 strategy_3
2 60-90 12 Repeat 0 0.8815792627486193 strategy_3
2 60-90 24 New 2 0.15672816174980553 strategy_2
2 60-90 24 Old 1 0.4659218363804922 strategy_2
2 60-90 24 Repeat 1 0.8758501344832903 strategy_2
2 60-90 36 New 1 0.437962717015704 strategy_2
2 60-90 36 Old 0 0.38038980910684894 strategy_2
2 60-90 36 Repeat 1 0.9282481411312358 strategy_3
2 60-90 48 New 0 0.6282543784964676 strategy_1
2 60-90 48 Old 1 0.6088513161002692 strategy_2
2 60-90 48 Repeat 3 0.34026536848029554 strategy_3
2 60-90 60 New 3 0.07885656303778943 strategy_1
2 60-90 60 Old 1 0.6466271322570204 strategy_3
2 60-90 60 Repeat 0 0.8767005213650039 strategy_2
2 60-90 72 New 1 0.15375455396176585 strategy_3
2 60-90 72 Old 1 0.23752744150124494 strategy_3
2 60-90 72 Repeat 1 0.6859205043032531 strategy_3
2 60-90 84 New 1 0.3906327120167483 strategy_1
2 60-90 84 Old 2 0.33568246624757914 strategy_1
2 60-90 84 Repeat 0 0.6679347737388965 strategy_2
2 90-100 12 New 2 0.192805305714691 strategy_3
2 90-100 12 Old 1 0.12407767859531083 strategy_3
2 90-100 12 Repeat 3 0.9894804066414016 strategy_3
2 90-100 24 New 1 0.7606325914789717 strategy_2
2 90-100 24 Old 0 0.6370781421707793 strategy_3
2 90-100 24 Repeat 3 0.8164196860334495 strategy_3
2 90-100 36 New 2 0.15879522523808476 strategy_1
2 90-100 36 Old 1 0.26166030086752146 strategy_3
2 90-100 36 Repeat 2 0.9253085348638621 strategy_2
2 90-100 48 New 1 0.6062379929352605 strategy_1
2 90-100 48 Old 0 0.5701148175530785 strategy_1
2 90-100 48 Repeat 0 0.7597026191486868 strategy_1
2 90-100 60 New 1 0.86365952344352 strategy_1
2 90-100 60 Old 0 0.4062820092418181 strategy_3
2 90-100 60 Repeat 1 0.8407383521887494 strategy_1
2 90-100 72 New 3 0.5031824021967019 strategy_3
2 90-100 72 Old 2 0.20747786347149832 strategy_3
2 90-100 72 Repeat 3 0.9343240070595654 strategy_2
2 90-100 84 New 2 0.7301933134374394 strategy_2
2 90-100 84 Old 1 0.4827789071013864 strategy_1
2 90-100 84 Repeat 0 0.8224423027360466 strategy_2
3 10-30 12 New 2 0.7701621853749034 strategy_1
3 10-30 12 Old 3 0.8018676064473043 strategy_3
3 10-30 12 Repeat 3 0.20611175138341975 strategy_2
3 10-30 24 New 1 0.5581476173674882 strategy_2
3 10-30 24 Old 2 0.5642198572737736 strategy_2
3 10-30 24 Repeat 2 0.03384331350031056 strategy_3
3 10-30 36 New 3 0.6840189234164086 strategy_2
3 10-30 36 Old 3 0.5243658563497826 strategy_1
3 10-30 36 Repeat 2 0.9429611587359796 strategy_2
3 10-30 48 New 1 0.2288302174536253 strategy_2
3 10-30 48 Old 0 0.1604764651221242 strategy_2
3 10-30 48 Repeat 2 0.8426147711983495 strategy_1
3 10-30 60 New 2 0.07121493327984285 strategy_1
3 10-30 60 Old 2 0.34917585986410604 strategy_3
3 10-30 60 Repeat 3 0.026872075625920422 strategy_2
3 10-30 72 New 2 0.865001324038859 strategy_1
3 10-30 72 Old 2 0.2708770173290128 strategy_3
3 10-30 72 Repeat 0 0.6849500096230458 strategy_2
3 10-30 84 New 0 0.9691894284404089 strategy_3
3 10-30 84 Old 3 0.5390601152918273 strategy_3
3 10-30 84 Repeat 0 0.3142354192999611 strategy_3
3 30-35 12 New 2 0.4410660812568653 strategy_3
3 30-35 12 Old 0 0.03925365760461064 strategy_1
3 30-35 12 Repeat 2 0.15981964344383615 strategy_1
3 30-35 24 New 3 0.17207236194635855 strategy_2
3 30-35 24 Old 3 0.5726092955386776 strategy_3
3 30-35 24 Repeat 3 0.25737850193208045 strategy_3
3 30-35 36 New 2 0.04615940276552488 strategy_1
3 30-35 36 Old 2 0.7385173615556415 strategy_3
3 30-35 36 Repeat 2 0.6026190332521771 strategy_3
3 30-35 48 New 0 0.5164808657108924 strategy_2
3 30-35 48 Old 0 0.26250596666199444 strategy_3
3 30-35 48 Repeat 3 0.3601403395303574 strategy_3
3 30-35 60 New 0 0.14444911397563442 strategy_1
3 30-35 60 Old 0 0.24879920777229836 strategy_2
3 30-35 60 Repeat 2 0.026756456284208308 strategy_1
3 30-35 72 New 3 0.8336899996680541 strategy_1
3 30-35 72 Old 1 0.24927172987833035 strategy_2
3 30-35 72 Repeat 3 0.2544897212668026 strategy_1
3 30-35 84 New 0 0.377549503267417 strategy_2
3 30-35 84 Old 0 0.9949125153170418 strategy_3
3 30-35 84 Repeat 1 0.330842946050104 strategy_1
3 35-50 12 New 3 0.6733772453907981 strategy_2
3 35-50 12 Old 3 0.05049482510616776 strategy_2
3 35-50 12 Repeat 2 0.958297855856014 strategy_2
3 35-50 24 New 3 0.6791647270189803 strategy_2
3 35-50 24 Old 0 0.14222836254068694 strategy_3
3 35-50 24 Repeat 0 0.3076255218234113 strategy_2
3 35-50 36 New 3 0.8069692308897948 strategy_2
3 35-50 36 Old 2 0.8371931537753058 strategy_3
3 35-50 36 Repeat 3 0.5297687609033581 strategy_2
3 35-50 48 New 0 0.14085581462866692 strategy_1
3 35-50 48 Old 0 0.3232274367468152 strategy_2
3 35-50 48 Repeat 0 0.9077565378132283 strategy_2
3 35-50 60 New 2 0.7603669487763169 strategy_3
3 35-50 60 Old 0 0.3754931094314944 strategy_3
3 35-50 60 Repeat 2 0.5216903077306887 strategy_1
3 35-50 72 New 1 0.2802586040482119 strategy_1
3 35-50 72 Old 0 0.7612518221626575 strategy_2
3 35-50 72 Repeat 2 0.7116079069843496 strategy_1
3 35-50 84 New 1 0.8041549158905681 strategy_2
3 35-50 84 Old 0 0.12840723983677638 strategy_1
3 35-50 84 Repeat 1 0.5106644894496161 strategy_3
3 50-60 12 New 3 0.5769374280834196 strategy_2
3 50-60 12 Old 2 0.5412419908439727 strategy_3
3 50-60 12 Repeat 1 0.5013223086161702 strategy_3
3 50-60 24 New 3 0.5212880254725624 strategy_3
3 50-60 24 Old 1 0.8999838642167087 strategy_2
3 50-60 24 Repeat 2 0.6966230557138793 strategy_3
3 50-60 36 New 1 0.8964241094837461 strategy_2
3 50-60 36 Old 1 0.3664348453383429 strategy_2
3 50-60 36 Repeat 2 0.5173223823047136 strategy_3
3 50-60 48 New 2 0.2632649186113182 strategy_1
3 50-60 48 Old 0 0.12959277692975046 strategy_2
3 50-60 48 Repeat 1 0.13143857668246361 strategy_3
3 50-60 60 New 0 0.10479610683643914 strategy_3
3 50-60 60 Old 3 0.07756115350424164 strategy_3
3 50-60 60 Repeat 0 0.7560905568276468 strategy_1
3 50-60 72 New 3 0.6628987389176336 strategy_1
3 50-60 72 Old 2 0.7258532534663442 strategy_1
3 50-60 72 Repeat 0 0.4355420676031867 strategy_1
3 50-60 84 New 1 0.47091813480895606 strategy_3
3 50-60 84 Old 3 0.0880065206864401 strategy_1
3 50-60 84 Repeat 3 0.48274556981110806 strategy_1
3 60-90 12 New 1 0.33647200552548173 strategy_2
3 60-90 12 Old 3 0.9521579798265745 strategy_2
3 60-90 12 Repeat 1 0.6789005173301544 strategy_1
3 60-90 24 New 0 0.1533162622157933 strategy_3
3 60-90 24 Old 3 0.7715496037336158 strategy_3
3 60-90 24 Repeat 3 0.09632722779018632 strategy_1
3 60-90 36 New 0 0.9397085237277906 strategy_1
3 60-90 36 Old 1 0.9949487907818488 strategy_1
3 60-90 36 Repeat 1 0.547148610152531 strategy_2
3 60-90 48 New 0 0.1269803755481198 strategy_3
3 60-90 48 Old 2 0.5858595098533202 strategy_2
3 60-90 48 Repeat 0 0.12956923140045473 strategy_1
3 60-90 60 New 3 0.6014084250621451 strategy_2
3 60-90 60 Old 0 0.3979472671173774 strategy_1
3 60-90 60 Repeat 2 0.3646984042968614 strategy_2
3 60-90 72 New 0 0.3626257861166319 strategy_1
3 60-90 72 Old 0 0.9991914264309449 strategy_3
3 60-90 72 Repeat 1 0.9697974560317263 strategy_1
3 60-90 84 New 0 0.4732227899867397 strategy_2
3 60-90 84 Old 0 0.6560199389984258 strategy_2
3 60-90 84 Repeat 0 0.3111433469226256 strategy_3
3 90-100 12 New 3 0.5552489920982417 strategy_3
3 90-100 12 Old 3 0.038021289629000754 strategy_2
3 90-100 12 Repeat 1 0.3092636124573116 strategy_1
3 90-100 24 New 0 0.5366003822722789 strategy_2
3 90-100 24 Old 2 0.4352579624942696 strategy_2
3 90-100 24 Repeat 0 0.2675441942790696 strategy_2
3 90-100 36 New 2 0.5166500726414828 strategy_1
3 90-100 36 Old 0 0.5445804763731319 strategy_1
3 90-100 36 Repeat 2 0.5319792424149197 strategy_1
3 90-100 48 New 2 0.47853255700477015 strategy_1
3 90-100 48 Old 1 0.00295538545261409 strategy_2
3 90-100 48 Repeat 0 0.7869794641117923 strategy_3
3 90-100 60 New 2 0.23368992395825317 strategy_2
3 90-100 60 Old 3 0.5088495626623084 strategy_3
3 90-100 60 Repeat 2 0.9466554484130905 strategy_1
3 90-100 72 New 0 0.39724762572631633 strategy_1
3 90-100 72 Old 3 0.3775331556690249 strategy_3
3 90-100 72 Repeat 0 0.5056850295946005 strategy_1
3 90-100 84 New 2 0.699704601170761 strategy_2
3 90-100 84 Old 0 0.25767027833389955 strategy_2
3 90-100 84 Repeat 3 0.9992673681910534 strategy_2
4 10-30 12 New 3 0.9630923688624984 strategy_1
4 10-30 12 Old 2 0.12581909193193963 strategy_3
4 10-30 12 Repeat 0 0.7183826709041836 strategy_1
4 10-30 24 New 2 0.24035897040205256 strategy_1
4 10-30 24 Old 2 0.438076485553327 strategy_3
4 10-30 24 Repeat 2 0.4931635488188897 strategy_3
4 10-30 36 New 3 0.9177827440173392 strategy_3
4 10-30 36 Old 3 0.1288813739332646 strategy_2
4 10-30 36 Repeat 3 0.9969951460476465 strategy_3
4 10-30 48 New 2 0.349289266326126 strategy_1
4 10-30 48 Old 3 0.1649112812470973 strategy_3
4 10-30 48 Repeat 1 0.31151277185693205 strategy_1
4 10-30 60 New 2 0.542340325587943 strategy_3
4 10-30 60 Old 1 0.881794424304119 strategy_1
4 10-30 60 Repeat 3 0.17327133846500054 strategy_1
4 10-30 72 New 1 0.895494124478602 strategy_3
4 10-30 72 Old 2 0.4398903666247952 strategy_2
4 10-30 72 Repeat 0 0.30142213883568214 strategy_3
4 10-30 84 New 0 0.23991280432819173 strategy_1
4 10-30 84 Old 0 0.03773521038617511 strategy_2
4 10-30 84 Repeat 2 0.45061007750953275 strategy_3
4 30-35 12 New 0 0.3151794618733724 strategy_2
4 30-35 12 Old 3 0.7400380593284996 strategy_3
4 30-35 12 Repeat 3 0.6854433538991956 strategy_3
4 30-35 24 New 2 0.659591138000141 strategy_3
4 30-35 24 Old 2 0.0395347708996141 strategy_3
4 30-35 24 Repeat 3 0.7107351866512287 strategy_3
4 30-35 36 New 3 0.10671348538587022 strategy_1
4 30-35 36 Old 1 0.7827684402986183 strategy_3
4 30-35 36 Repeat 1 0.21687603296510882 strategy_3
4 30-35 48 New 1 0.20571817607674692 strategy_1
4 30-35 48 Old 3 0.8629358464357805 strategy_3
4 30-35 48 Repeat 2 0.8658768338745779 strategy_2
4 30-35 60 New 0 0.8173256971879049 strategy_1
4 30-35 60 Old 0 0.9251842742289067 strategy_3
4 30-35 60 Repeat 3 0.8566669474954735 strategy_3
4 30-35 72 New 2 0.08696496600377979 strategy_3
4 30-35 72 Old 1 0.524106336232745 strategy_1
4 30-35 72 Repeat 0 0.6269059553774684 strategy_1
4 30-35 84 New 3 0.29159009230515265 strategy_1
4 30-35 84 Old 3 0.7989569759472197 strategy_3
4 30-35 84 Repeat 2 0.1648124672358292 strategy_2
4 35-50 12 New 2 0.10634125828950947 strategy_2
4 35-50 12 Old 0 0.37649476190449804 strategy_1
4 35-50 12 Repeat 1 0.2176582128639386 strategy_1
4 35-50 24 New 1 0.04145361473843345 strategy_2
4 35-50 24 Old 2 0.21427244420811653 strategy_2
4 35-50 24 Repeat 2 0.8750158790542099 strategy_1
4 35-50 36 New 3 0.3545647487185728 strategy_2
4 35-50 36 Old 0 0.6069553851839269 strategy_1
4 35-50 36 Repeat 0 0.35931319756155333 strategy_3
4 35-50 48 New 2 0.31837839920037325 strategy_1
4 35-50 48 Old 2 0.29571222562330457 strategy_2
4 35-50 48 Repeat 3 0.43824474698945803 strategy_1
4 35-50 60 New 1 0.14473473807262638 strategy_2
4 35-50 60 Old 1 0.2694332104893784 strategy_2
4 35-50 60 Repeat 2 0.5126752858519995 strategy_3
4 35-50 72 New 2 0.2515807982021572 strategy_2
4 35-50 72 Old 3 0.18570918085906263 strategy_1
4 35-50 72 Repeat 1 0.8471375184751407 strategy_2
4 35-50 84 New 0 0.3455777294117195 strategy_3
4 35-50 84 Old 1 0.03348528377539872 strategy_1
4 35-50 84 Repeat 3 0.03591674092467212 strategy_3
4 50-60 12 New 2 0.8888547121159908 strategy_2
4 50-60 12 Old 3 0.19545083450161227 strategy_1
4 50-60 12 Repeat 2 0.21523791235803724 strategy_1
4 50-60 24 New 2 0.22436629442337308 strategy_2
4 50-60 24 Old 1 0.19591339433228283 strategy_3
4 50-60 24 Repeat 0 0.1774892036527349 strategy_3
4 50-60 36 New 0 0.22740058812936415 strategy_1
4 50-60 36 Old 1 0.6823281992827276 strategy_3
4 50-60 36 Repeat 0 0.8159101303835229 strategy_2
4 50-60 48 New 0 0.35185004862061275 strategy_1
4 50-60 48 Old 1 0.0908892720975375 strategy_3
4 50-60 48 Repeat 3 0.7712490774280636 strategy_2
4 50-60 60 New 3 0.3821592720228576 strategy_3
4 50-60 60 Old 2 0.9445017902164842 strategy_2
4 50-60 60 Repeat 3 0.2167228372158817 strategy_1
4 50-60 72 New 3 0.903452856929479 strategy_1
4 50-60 72 Old 3 0.8389900896702637 strategy_1
4 50-60 72 Repeat 2 0.0294672007615725 strategy_3
4 50-60 84 New 3 0.9120143908170124 strategy_2
4 50-60 84 Old 1 0.6357072616511505 strategy_1
4 50-60 84 Repeat 0 0.30067693508659366 strategy_1
4 60-90 12 New 3 0.4174558543079461 strategy_2
4 60-90 12 Old 3 0.03221865996446904 strategy_1
4 60-90 12 Repeat 1 0.0028583823871991543 strategy_3
4 60-90 24 New 0 0.23333757444621428 strategy_2
4 60-90 24 Old 1 0.8670013324734089 strategy_1
4 60-90 24 Repeat 3 0.7356289753854134 strategy_3
4 60-90 36 New 1 0.7458053972876498 strategy_3
4 60-90 36 Old 2 0.5731977628902106 strategy_3
4 60-90 36 Repeat 0 0.6312321148576973 strategy_2
4 60-90 48 New 3 0.2509319506448442 strategy_1
4 60-90 48 Old 0 0.2600863639134582 strategy_1
4 60-90 48 Repeat 1 0.6399865327955012 strategy_2
4 60-90 60 New 0 0.5573735703747089 strategy_2
4 60-90 60 Old 1 0.08653599497569409 strategy_1
4 60-90 60 Repeat 1 0.1735755565870436 strategy_3
4 60-90 72 New 1 0.9018120464468765 strategy_1
4 60-90 72 Old 2 0.6706219929529595 strategy_2
4 60-90 72 Repeat 3 0.9662207747610283 strategy_2
4 60-90 84 New 3 0.3309577968933737 strategy_1
4 60-90 84 Old 1 0.7097317251587758 strategy_3
4 60-90 84 Repeat 0 0.009392069436093498 strategy_2
4 90-100 12 New 3 0.6210558347004063 strategy_2
4 90-100 12 Old 0 0.40996897199693183 strategy_1
4 90-100 12 Repeat 2 0.5812883437123924 strategy_1
4 90-100 24 New 2 0.10507672627950326 strategy_1
4 90-100 24 Old 0 0.09665904887480181 strategy_3
4 90-100 24 Repeat 0 0.5719515662953726 strategy_1
4 90-100 36 New 1 0.2589179064743753 strategy_2
4 90-100 36 Old 0 0.8290140802370363 strategy_2
4 90-100 36 Repeat 1 0.481984622126138 strategy_3
4 90-100 48 New 3 0.3688618128315533 strategy_3
4 90-100 48 Old 1 0.09805956144643768 strategy_2
4 90-100 48 Repeat 0 0.8987785844257832 strategy_1
4 90-100 60 New 0 0.18115219102300117 strategy_1
4 90-100 60 Old 2 0.1510340224723271 strategy_1
4 90-100 60 Repeat 2 0.4724129261048544 strategy_2
4 90-100 72 New 3 0.806942562534917 strategy_2
4 90-100 72 Old 0 0.19625467169137323 strategy_3
4 90-100 72 Repeat 3 0.2090735257405465 strategy_3
4 90-100 84 New 3 0.43617726444013916 strategy_1
4 90-100 84 Old 1 0.022478970084258143 strategy_1
4 90-100 84 Repeat 2 0.6394025449562758 strategy_2
5 10-30 12 New 2 0.02306606926489252 strategy_1
5 10-30 12 Old 1 0.972524015901075 strategy_1
5 10-30 12 Repeat 2 0.4386853217504434 strategy_2
5 10-30 24 New 3 0.08035429620994383 strategy_2
5 10-30 24 Old 3 0.6478105283147444 strategy_2
5 10-30 24 Repeat 3 0.371336431713978 strategy_3
5 10-30 36 New 3 0.4065368837677016 strategy_3
5 10-30 36 Old 0 0.7892579253981731 strategy_2
5 10-30 36 Repeat 2 0.24009385832423769 strategy_3
5 10-30 48 New 0 0.310287498426437 strategy_1
5 10-30 48 Old 0 0.574470525238975 strategy_3
5 10-30 48 Repeat 3 0.6800132275409757 strategy_3
5 10-30 60 New 2 0.23858951488265967 strategy_2
5 10-30 60 Old 1 0.20129545519185088 strategy_2
5 10-30 60 Repeat 2 0.5687457602149902 strategy_1
5 10-30 72 New 1 0.08353032849574638 strategy_3
5 10-30 72 Old 3 0.2999295780154253 strategy_1
5 10-30 72 Repeat 1 0.12899759903608798 strategy_3
5 10-30 84 New 1 0.32277710752210564 strategy_3
5 10-30 84 Old 1 0.5886395771489228 strategy_3
5 10-30 84 Repeat 0 0.08779018977796083 strategy_2
5 30-35 12 New 2 0.7253474928027759 strategy_2
5 30-35 12 Old 2 0.9819934720047088 strategy_1
5 30-35 12 Repeat 2 0.7975601838086368 strategy_1
5 30-35 24 New 0 0.6803001889973347 strategy_1
5 30-35 24 Old 3 0.17152696639600495 strategy_3
5 30-35 24 Repeat 0 0.2396281700485574 strategy_1
5 30-35 36 New 0 0.9552244480309005 strategy_3
5 30-35 36 Old 2 0.08689909883088742 strategy_2
5 30-35 36 Repeat 2 0.6042687018694934 strategy_2
5 30-35 48 New 3 0.505041629934731 strategy_3
5 30-35 48 Old 1 0.7703274953449365 strategy_3
5 30-35 48 Repeat 2 0.6832283939915492 strategy_2
5 30-35 60 New 1 0.4353483994486246 strategy_2
5 30-35 60 Old 3 0.2732095404604823 strategy_2
5 30-35 60 Repeat 0 0.8256141111289901 strategy_1
5 30-35 72 New 2 0.6862168766946132 strategy_2
5 30-35 72 Old 0 0.3385985013607147 strategy_1
5 30-35 72 Repeat 1 0.5537963956137166 strategy_1
5 30-35 84 New 1 0.17717267070091747 strategy_3
5 30-35 84 Old 0 0.3723355592760552 strategy_3
5 30-35 84 Repeat 2 0.6333951228952374 strategy_1
5 35-50 12 New 2 0.3754064535912346 strategy_3
5 35-50 12 Old 3 0.7496633251187333 strategy_1
5 35-50 12 Repeat 0 0.45230990742648225 strategy_2
5 35-50 24 New 2 0.0017895641435190512 strategy_3
5 35-50 24 Old 1 0.6094784222687505 strategy_2
5 35-50 24 Repeat 3 0.4782920824249187 strategy_3
5 35-50 36 New 1 0.30241554912321 strategy_2
5 35-50 36 Old 0 0.6627220555624442 strategy_2
5 35-50 36 Repeat 0 0.3730259834890397 strategy_2
5 35-50 48 New 1 0.06207727715809552 strategy_2
5 35-50 48 Old 3 0.2610368744675642 strategy_3
5 35-50 48 Repeat 0 0.9228549775606375 strategy_3
5 35-50 60 New 2 0.07860553015606053 strategy_2
5 35-50 60 Old 2 0.07810812010558943 strategy_2
5 35-50 60 Repeat 2 0.6983823078495268 strategy_2
5 35-50 72 New 1 0.6534095972690778 strategy_3
5 35-50 72 Old 2 0.9496139899414996 strategy_1
5 35-50 72 Repeat 0 0.3737591786660962 strategy_2
5 35-50 84 New 2 0.6032765647723584 strategy_1
5 35-50 84 Old 0 0.47651178687960183 strategy_3
5 35-50 84 Repeat 1 0.5367989976519909 strategy_3
5 50-60 12 New 2 0.675923584219132 strategy_3
5 50-60 12 Old 1 0.6619429661391547 strategy_3
5 50-60 12 Repeat 3 0.33447630507922665 strategy_2
5 50-60 24 New 1 0.7446402744786155 strategy_3
5 50-60 24 Old 3 0.4918838670730834 strategy_2
5 50-60 24 Repeat 3 0.7787744843722255 strategy_2
5 50-60 36 New 0 0.06236674146381593 strategy_1
5 50-60 36 Old 2 0.7189934090990704 strategy_2
5 50-60 36 Repeat 3 0.6673465407166972 strategy_1
5 50-60 48 New 0 0.18318339321801802 strategy_2
5 50-60 48 Old 0 0.22651854030147456 strategy_2
5 50-60 48 Repeat 2 0.4047534149746772 strategy_1
5 50-60 60 New 2 0.07216604749276057 strategy_2
5 50-60 60 Old 3 0.8136492009035363 strategy_1
5 50-60 60 Repeat 3 0.18503803819399345 strategy_3
5 50-60 72 New 1 0.0523398095369908 strategy_2
5 50-60 72 Old 2 0.9590097810267988 strategy_2
5 50-60 72 Repeat 3 0.5473903913438309 strategy_2
5 50-60 84 New 1 0.641523569514603 strategy_3
5 50-60 84 Old 0 0.8267976714005056 strategy_1
5 50-60 84 Repeat 2 0.9683739307437966 strategy_3
5 60-90 12 New 2 0.9443995108044821 strategy_3
5 60-90 12 Old 0 0.7436565653891408 strategy_3
5 60-90 12 Repeat 0 0.9546457316669565 strategy_3
5 60-90 24 New 0 0.5150281395467492 strategy_1
5 60-90 24 Old 1 0.06164665397200619 strategy_3
5 60-90 24 Repeat 3 0.8784501476008395 strategy_1
5 60-90 36 New 1 0.23153090989532055 strategy_2
5 60-90 36 Old 2 0.8640034221271146 strategy_3
5 60-90 36 Repeat 0 0.4841587178799749 strategy_3
5 60-90 48 New 2 0.41500984043741806 strategy_1
5 60-90 48 Old 1 0.22027196365193646 strategy_3
5 60-90 48 Repeat 0 0.7313369996542063 strategy_1
5 60-90 60 New 3 0.6089729584368101 strategy_1
5 60-90 60 Old 3 0.6234825287824759 strategy_2
5 60-90 60 Repeat 1 0.1574571886351498 strategy_1
5 60-90 72 New 1 0.5482768977615983 strategy_1
5 60-90 72 Old 2 0.31371895772153857 strategy_2
5 60-90 72 Repeat 3 0.4447122852443369 strategy_1
5 60-90 84 New 3 0.5033496773644015 strategy_1
5 60-90 84 Old 1 0.2598664780038773 strategy_1
5 60-90 84 Repeat 0 0.6357979295762893 strategy_3
5 90-100 12 New 3 0.7538609785890951 strategy_1
5 90-100 12 Old 3 0.8244391198929998 strategy_3
5 90-100 12 Repeat 3 0.7706448804048328 strategy_1
5 90-100 24 New 0 0.060733604113258455 strategy_2
5 90-100 24 Old 1 0.11813575048550795 strategy_3
5 90-100 24 Repeat 0 0.43717942803174836 strategy_3
5 90-100 36 New 1 0.40945409210637607 strategy_2
5 90-100 36 Old 3 0.9695263197286931 strategy_3
5 90-100 36 Repeat 3 0.5190299203225246 strategy_3
5 90-100 48 New 0 0.45353752242570844 strategy_2
5 90-100 48 Old 0 0.5773339776839155 strategy_2
5 90-100 48 Repeat 1 0.0044482980371524095 strategy_1
5 90-100 60 New 1 0.11367911425015431 strategy_2
5 90-100 60 Old 1 0.604053747640699 strategy_2
5 90-100 60 Repeat 1 0.7942076202290972 strategy_1
5 90-100 72 New 2 0.8378821703247232 strategy_3
5 90-100 72 Old 1 0.9090158878336864 strategy_3
5 90-100 72 Repeat 3 0.5642199420231976 strategy_2
5 90-100 84 New 0 0.5066521900291887 strategy_3
5 90-100 84 Old 1 0.9462271876167943 strategy_2
5 90-100 84 Repeat 3 0.23324517491452956 strategy_1
6 10-30 12 New 0 0.9289779762483067 strategy_3
6 10-30 12 Old 2 0.6023739559379266 strategy_2
6 10-30 12 Repeat 2 0.8207033723130714 strategy_3
6 10-30 24 New 1 0.48826817189543326 strategy_1
6 10-30 24 Old 3 0.8974008440437634 strategy_1
6 10-30 24 Repeat 1 0.7131798901162443 strategy_3
6 10-30 36 New 0 0.2619466775398094 strategy_3
6 10-30 36 Old 1 0.023095405604976915 strategy_2
6 10-30 36 Repeat 1 0.8403079621170515 strategy_3
6 10-30 48 New 2 0.07408017811516854 strategy_2
6 10-30 48 Old 3 0.27097565024779524 strategy_1
6 10-30 48 Repeat 0 0.13345795949316563 strategy_2
6 10-30 60 New 2 0.6796825793521355 strategy_1
6 10-30 60 Old 0 0.5308476040185592 strategy_1
6 10-30 60 Repeat 3 0.8476419009520684 strategy_2
6 10-30 72 New 1 0.22858831249160272 strategy_1
6 10-30 72 Old 2 0.14627687542070678 strategy_2
6 10-30 72 Repeat 2 0.15108195644563016 strategy_3
6 10-30 84 New 1 0.0769899093110763 strategy_1
6 10-30 84 Old 0 0.06380197805836196 strategy_3
6 10-30 84 Repeat 1 0.10970721897932778 strategy_1
6 30-35 12 New 0 0.8732927949590941 strategy_1
6 30-35 12 Old 2 0.4270908544430062 strategy_2
6 30-35 12 Repeat 2 0.4780950421324759 strategy_3
6 30-35 24 New 3 0.21873333660387162 strategy_2
6 30-35 24 Old 1 0.1745234400941672 strategy_1
6 30-35 24 Repeat 1 0.719095677566103 strategy_1
6 30-35 36 New 2 0.45898499105477586 strategy_3
6 30-35 36 Old 3 0.9884131704805791 strategy_3
6 30-35 36 Repeat 0 0.5773135806015367 strategy_1
6 30-35 48 New 0 0.9839544669132833 strategy_1
6 30-35 48 Old 0 0.4535459401240546 strategy_1
6 30-35 48 Repeat 1 0.753495801237302 strategy_2
6 30-35 60 New 3 0.7242182960175656 strategy_3
6 30-35 60 Old 2 0.5100997035864459 strategy_3
6 30-35 60 Repeat 1 0.8408644732904571 strategy_3
6 30-35 72 New 0 0.6452926904287177 strategy_3
6 30-35 72 Old 2 0.708798371242278 strategy_3
6 30-35 72 Repeat 2 0.9498289597570393 strategy_3
6 30-35 84 New 3 0.7379167391857628 strategy_1
6 30-35 84 Old 0 0.4594805369308522 strategy_3
6 30-35 84 Repeat 1 0.31262739197353107 strategy_2
6 35-50 12 New 0 0.8183275832054326 strategy_3
6 35-50 12 Old 3 0.6669899343239469 strategy_1
6 35-50 12 Repeat 0 0.9164455947758171 strategy_1
6 35-50 24 New 3 0.06560689254259888 strategy_2
6 35-50 24 Old 2 0.9413442351215088 strategy_2
6 35-50 24 Repeat 0 0.2809528551902064 strategy_1
6 35-50 36 New 2 0.78119587683795 strategy_3
6 35-50 36 Old 3 0.5536418705045558 strategy_1
6 35-50 36 Repeat 3 0.9620538925362595 strategy_3
6 35-50 48 New 3 0.6248743849129473 strategy_3
6 35-50 48 Old 2 0.42769888297889247 strategy_1
6 35-50 48 Repeat 2 0.9416148146155301 strategy_2
6 35-50 60 New 1 0.9750927132909321 strategy_2
6 35-50 60 Old 3 0.08434350943873792 strategy_1
6 35-50 60 Repeat 3 0.713151746504562 strategy_1
6 35-50 72 New 0 0.4043250730656045 strategy_3
6 35-50 72 Old 1 0.49903522355691465 strategy_3
6 35-50 72 Repeat 2 0.14289448989738018 strategy_3
6 35-50 84 New 2 0.9852677167253373 strategy_2
6 35-50 84 Old 1 0.3407331927291676 strategy_1
6 35-50 84 Repeat 2 0.19481908057250297 strategy_2
6 50-60 12 New 3 0.8523511031933249 strategy_3
6 50-60 12 Old 1 0.8640584531648949 strategy_1
6 50-60 12 Repeat 2 0.7991780561068995 strategy_2
6 50-60 24 New 2 0.8593141241444237 strategy_2
6 50-60 24 Old 0 0.6102129587437267 strategy_2
6 50-60 24 Repeat 1 0.6872923798577707 strategy_2
6 50-60 36 New 1 0.5062430760310489 strategy_2
6 50-60 36 Old 0 0.9402059483115023 strategy_2
6 50-60 36 Repeat 1 0.2231518748011151 strategy_1
6 50-60 48 New 3 0.12124276565853342 strategy_1
6 50-60 48 Old 1 0.15657851472341566 strategy_1
6 50-60 48 Repeat 3 0.9581374996130354 strategy_1
6 50-60 60 New 1 0.6545296162269041 strategy_2
6 50-60 60 Old 3 0.3475449023374746 strategy_3
6 50-60 60 Repeat 1 0.708963388594875 strategy_2
6 50-60 72 New 0 0.3886451735979859 strategy_1
6 50-60 72 Old 0 0.6339405712578656 strategy_2
6 50-60 72 Repeat 1 0.015867110932176298 strategy_3
6 50-60 84 New 1 0.1136524952308231 strategy_1
6 50-60 84 Old 0 0.3406235295539146 strategy_2
6 50-60 84 Repeat 2 0.07573711840516806 strategy_2
6 60-90 12 New 3 0.5574168538542658 strategy_1
6 60-90 12 Old 2 0.02596547464826282 strategy_1
6 60-90 12 Repeat 3 0.27967132402066097 strategy_1
6 60-90 24 New 0 0.7136774193496959 strategy_2
6 60-90 24 Old 0 0.09363525579340604 strategy_3
6 60-90 24 Repeat 2 0.3622813245253159 strategy_2
6 60-90 36 New 3 0.6930791517655586 strategy_2
6 60-90 36 Old 2 0.28081362325232484 strategy_1
6 60-90 36 Repeat 1 0.24934626955720962 strategy_3
6 60-90 48 New 0 0.8176009009127312 strategy_1
6 60-90 48 Old 2 0.8149415627134954 strategy_1
6 60-90 48 Repeat 0 0.6168376878854724 strategy_1
6 60-90 60 New 3 0.6956448870520717 strategy_2
6 60-90 60 Old 3 0.7382463692360821 strategy_3
6 60-90 60 Repeat 1 0.8302873718005885 strategy_3
6 60-90 72 New 2 0.7257003673636052 strategy_2
6 60-90 72 Old 0 0.08275452228494329 strategy_3
6 60-90 72 Repeat 3 0.9182468182792342 strategy_2
6 60-90 84 New 0 0.3677747987887158 strategy_2
6 60-90 84 Old 3 0.3797831781530615 strategy_1
6 60-90 84 Repeat 0 0.8629012200919449 strategy_3
6 90-100 12 New 2 0.7937025010371355 strategy_2
6 90-100 12 Old 2 0.02129128266390401 strategy_1
6 90-100 12 Repeat 1 0.4941604493120906 strategy_3
6 90-100 24 New 0 0.74683655618623 strategy_3
6 90-100 24 Old 0 0.6203273713821507 strategy_2
6 90-100 24 Repeat 1 0.36743924288355 strategy_3
6 90-100 36 New 2 0.4329520350569471 strategy_3
6 90-100 36 Old 0 0.5315212615406963 strategy_3
6 90-100 36 Repeat 3 0.7542869680344788 strategy_3
6 90-100 48 New 1 0.8311618030478364 strategy_1
6 90-100 48 Old 2 0.4529512712011231 strategy_2
6 90-100 48 Repeat 1 0.5656785238688072 strategy_3
6 90-100 60 New 1 0.33232373684117167 strategy_2
6 90-100 60 Old 2 0.5792622676131084 strategy_1
6 90-100 60 Repeat 2 0.8723541469652963 strategy_1
6 90-100 72 New 2 0.5380538357776677 strategy_3
6 90-100 72 Old 0 0.7656230870018373 strategy_3
6 90-100 72 Repeat 2 0.3194900098192843 strategy_1
6 90-100 84 New 3 0.9656275655712854 strategy_1
6 90-100 84 Old 1 0.20052941859184692 strategy_1
6 90-100 84 Repeat 3 0.9040068016613223 strategy_1
7 10-30 12 New 0 0.665656753538153 strategy_2
7 10-30 12 Old 3 0.6145031749873138 strategy_3
7 10-30 12 Repeat 2 0.5192554236034593 strategy_2
7 10-30 24 New 0 0.5336343397996824 strategy_1
7 10-30 24 Old 2 0.6575816973568228 strategy_1
7 10-30 24 Repeat 0 0.14470009377144777 strategy_3
7 10-30 36 New 1 0.08122629422228766 strategy_3
7 10-30 36 Old 3 0.3948723876160213 strategy_1
7 10-30 36 Repeat 3 0.9474169750936718 strategy_2
7 10-30 48 New 2 0.7345952791438428 strategy_2
7 10-30 48 Old 2 0.1093123514643708 strategy_3
7 10-30 48 Repeat 1 0.307355316917472 strategy_1
7 10-30 60 New 1 0.9196414155633245 strategy_3
7 10-30 60 Old 3 0.2552559150944641 strategy_2
7 10-30 60 Repeat 3 0.2067885933688598 strategy_2
7 10-30 72 New 0 0.23912135187424233 strategy_1
7 10-30 72 Old 1 0.9541374886175833 strategy_2
7 10-30 72 Repeat 2 0.6240096260343649 strategy_2
7 10-30 84 New 1 0.43214106112933004 strategy_2
7 10-30 84 Old 3 0.043017971557021806 strategy_1
7 10-30 84 Repeat 2 0.5493347096409288 strategy_1
7 30-35 12 New 1 0.23304769779289947 strategy_3
7 30-35 12 Old 3 0.790601650483149 strategy_2
7 30-35 12 Repeat 3 0.11032130883430014 strategy_2
7 30-35 24 New 2 0.885520280092438 strategy_3
7 30-35 24 Old 2 0.8559055812499223 strategy_1
7 30-35 24 Repeat 0 0.6770980636491696 strategy_1
7 30-35 36 New 0 0.8324842640812352 strategy_3
7 30-35 36 Old 2 0.4664566447891696 strategy_1
7 30-35 36 Repeat 3 0.6859504700676651 strategy_2
7 30-35 48 New 1 0.30690638677137927 strategy_1
7 30-35 48 Old 2 0.17482693151280204 strategy_2
7 30-35 48 Repeat 0 0.955012338883324 strategy_2
7 30-35 60 New 0 0.23558463149048237 strategy_1
7 30-35 60 Old 1 0.8355096076713742 strategy_2
7 30-35 60 Repeat 1 0.5447933156364372 strategy_1
7 30-35 72 New 2 0.23611282639545683 strategy_2
7 30-35 72 Old 3 0.36166028200333944 strategy_2
7 30-35 72 Repeat 0 0.7828850535194426 strategy_1
7 30-35 84 New 0 0.9423218334931819 strategy_3
7 30-35 84 Old 1 0.7324252049586684 strategy_2
7 30-35 84 Repeat 1 0.17406705242288767 strategy_3
7 35-50 12 New 3 0.9261119641744961 strategy_2
7 35-50 12 Old 3 0.9809681846232586 strategy_2
7 35-50 12 Repeat 2 0.3510199546240107 strategy_3
7 35-50 24 New 2 0.5862802533947475 strategy_2
7 35-50 24 Old 3 0.5461023109523149 strategy_2
7 35-50 24 Repeat 3 0.4204478786975854 strategy_3
7 35-50 36 New 1 0.7550377127006368 strategy_3
7 35-50 36 Old 3 0.7768396184891959 strategy_3
7 35-50 36 Repeat 1 0.6112696054175991 strategy_1
7 35-50 48 New 3 0.9366233499574604 strategy_2
7 35-50 48 Old 0 0.3505489232152913 strategy_2
7 35-50 48 Repeat 3 0.011381683606243476 strategy_1
7 35-50 60 New 1 0.9736987437915097 strategy_3
7 35-50 60 Old 2 0.023020395803724836 strategy_3
7 35-50 60 Repeat 3 0.11089027806191631 strategy_3
7 35-50 72 New 0 0.13090217981151864 strategy_2
7 35-50 72 Old 1 0.19830119862799533 strategy_2
7 35-50 72 Repeat 0 0.35811163006191804 strategy_1
7 35-50 84 New 1 0.8900923452090145 strategy_3
7 35-50 84 Old 0 0.5910706939567514 strategy_2
7 35-50 84 Repeat 2 0.8278074487644335 strategy_2
7 50-60 12 New 3 0.23138509589754164 strategy_1
7 50-60 12 Old 2 0.7704351972384642 strategy_2
7 50-60 12 Repeat 2 0.39578333936689325 strategy_2
7 50-60 24 New 0 0.5627223891102361 strategy_3
7 50-60 24 Old 0 0.6471829632742582 strategy_3
7 50-60 24 Repeat 0 0.29455456620062503 strategy_3
7 50-60 36 New 1 0.5159179622248473 strategy_2
7 50-60 36 Old 1 0.979342748879862 strategy_2
7 50-60 36 Repeat 2 0.36297756734963604 strategy_2
7 50-60 48 New 3 0.930484364946697 strategy_3
7 50-60 48 Old 3 0.7415386860233808 strategy_3
7 50-60 48 Repeat 0 0.360442865015315 strategy_1
7 50-60 60 New 3 0.7808809081962899 strategy_1
7 50-60 60 Old 0 0.07692319251651025 strategy_2
7 50-60 60 Repeat 3 0.06184064518341703 strategy_3
7 50-60 72 New 1 0.4302597193473442 strategy_1
7 50-60 72 Old 3 0.9145230397537278 strategy_2
7 50-60 72 Repeat 1 0.7810144884883811 strategy_3
7 50-60 84 New 2 0.2611589183512155 strategy_1
7 50-60 84 Old 1 0.27549585233604357 strategy_2
7 50-60 84 Repeat 0 0.516712487543923 strategy_2
7 60-90 12 New 0 0.8410799238535858 strategy_1
7 60-90 12 Old 0 0.7768242486262621 strategy_2
7 60-90 12 Repeat 1 0.6520465487610179 strategy_1
7 60-90 24 New 2 0.8948612160697728 strategy_3
7 60-90 24 Old 0 0.20030167830992618 strategy_1
7 60-90 24 Repeat 3 0.3169005159234909 strategy_3
7 60-90 36 New 2 0.011879841246807854 strategy_3
7 60-90 36 Old 1 0.11914357341213955 strategy_3
7 60-90 36 Repeat 2 0.32727247861361763 strategy_3
7 60-90 48 New 0 0.5897575222721222 strategy_2
7 60-90 48 Old 2 0.8722106367164749 strategy_2
7 60-90 48 Repeat 2 0.2880110917213926 strategy_1
7 60-90 60 New 0 0.8309183862476459 strategy_1
7 60-90 60 Old 2 0.2677123891195463 strategy_1
7 60-90 60 Repeat 2 0.45543847893792244 strategy_2
7 60-90 72 New 3 0.7212148782170454 strategy_2
7 60-90 72 Old 2 0.19121273728314614 strategy_3
7 60-90 72 Repeat 3 0.6268356938497374 strategy_1
7 60-90 84 New 1 0.05994652186428473 strategy_3
7 60-90 84 Old 2 0.9402308269479059 strategy_2
7 60-90 84 Repeat 3 0.6503141105820909 strategy_3
7 90-100 12 New 1 0.9311833390094894 strategy_1
7 90-100 12 Old 3 0.34835963512796697 strategy_2
7 90-100 12 Repeat 0 0.9672776652790219 strategy_2
7 90-100 24 New 1 0.5251937728087043 strategy_2
7 90-100 24 Old 3 0.5221707034158691 strategy_3
7 90-100 24 Repeat 1 0.04595957389224503 strategy_1
7 90-100 36 New 1 0.848340426881514 strategy_3
7 90-100 36 Old 2 0.42499249805198147 strategy_2
7 90-100 36 Repeat 3 0.20275646360860233 strategy_1
7 90-100 48 New 1 0.288084131110677 strategy_3
7 90-100 48 Old 2 0.18149275071166915 strategy_2
7 90-100 48 Repeat 0 0.2086674520516445 strategy_3
7 90-100 60 New 1 0.994394361702284 strategy_2
7 90-100 60 Old 0 0.8643456190177843 strategy_1
7 90-100 60 Repeat 0 0.3353762852087945 strategy_2
7 90-100 72 New 2 0.9212731350691066 strategy_2
7 90-100 72 Old 0 0.9115909657758892 strategy_3
7 90-100 72 Repeat 1 0.5519965232755063 strategy_3
7 90-100 84 New 3 0.6100611222418134 strategy_2
7 90-100 84 Old 1 0.19662943335717986 strategy_1
7 90-100 84 Repeat 1 0.8871272030201988 strategy_2
8 10-30 12 New 1 0.2697051592011601 strategy_2
8 10-30 12 Old 3 0.08671489035102986 strategy_3
8 10-30 12 Repeat 0 0.48764934483030153 strategy_2
8 10-30 24 New 1 0.04480330188570292 strategy_2
8 10-30 24 Old 2 0.006599639205591701 strategy_3
8 10-30 24 Repeat 1 0.8437948417756237 strategy_3
8 10-30 36 New 2 0.30060909285964477 strategy_2
8 10-30 36 Old 1 0.88476163766716 strategy_3
8 10-30 36 Repeat 3 0.45023288680135143 strategy_1
8 10-30 48 New 0 0.3976383135350463 strategy_3
8 10-30 48 Old 1 0.8788789805857413 strategy_1
8 10-30 48 Repeat 1 0.051652747473515115 strategy_3
8 10-30 60 New 1 0.01763060217961998 strategy_3
8 10-30 60 Old 3 0.32512143108212477 strategy_3
8 10-30 60 Repeat 0 0.9197414094853504 strategy_3
8 10-30 72 New 0 0.2034232784290919 strategy_1
8 10-30 72 Old 2 0.643560282530638 strategy_3
8 10-30 72 Repeat 2 0.2801258126988039 strategy_1
8 10-30 84 New 1 0.04619547904861565 strategy_2
8 10-30 84 Old 3 0.9219875865458335 strategy_2
8 10-30 84 Repeat 3 0.7687421704565532 strategy_2
8 30-35 12 New 3 0.8985954352642735 strategy_2
8 30-35 12 Old 0 0.0915659006685613 strategy_2
8 30-35 12 Repeat 0 0.8275654945166898 strategy_3
8 30-35 24 New 2 0.49451685346996044 strategy_3
8 30-35 24 Old 3 0.01693966376612477 strategy_3
8 30-35 24 Repeat 2 0.7270357573972445 strategy_1
8 30-35 36 New 3 0.01209124875992218 strategy_3
8 30-35 36 Old 1 0.6764286383088423 strategy_3
8 30-35 36 Repeat 3 0.22310901118503024 strategy_2
8 30-35 48 New 2 0.3991801502752599 strategy_2
8 30-35 48 Old 0 0.6077886448359076 strategy_1
8 30-35 48 Repeat 3 0.8737593125562265 strategy_3
8 30-35 60 New 3 0.04450019176744169 strategy_2
8 30-35 60 Old 3 0.36757669464947473 strategy_2
8 30-35 60 Repeat 0 0.8431785024520416 strategy_2
8 30-35 72 New 2 0.5169372176583548 strategy_3
8 30-35 72 Old 3 0.27628663846297286 strategy_1
8 30-35 72 Repeat 0 0.46329979193939896 strategy_1
8 30-35 84 New 1 0.9055166229792672 strategy_2
8 30-35 84 Old 0 0.6690634894323204 strategy_1
8 30-35 84 Repeat 1 0.1968589687788448 strategy_1
8 35-50 12 New 0 0.3802530484111327 strategy_3
8 35-50 12 Old 2 0.8038388968190963 strategy_1
8 35-50 12 Repeat 1 0.1733222402577873 strategy_2
8 35-50 24 New 2 0.22267048734383543 strategy_2
8 35-50 24 Old 3 0.5056639551803949 strategy_1
8 35-50 24 Repeat 0 0.4482728087352633 strategy_1
8 35-50 36 New 2 0.777333031953209 strategy_3
8 35-50 36 Old 1 0.9002246676966713 strategy_3
8 35-50 36 Repeat 1 0.8261867185693723 strategy_2
8 35-50 48 New 0 0.5538871034959091 strategy_3
8 35-50 48 Old 0 0.9155151788594916 strategy_1
8 35-50 48 Repeat 0 0.3727484984399655 strategy_2
8 35-50 60 New 0 0.9785481229164618 strategy_2
8 35-50 60 Old 3 0.31475426559061326 strategy_2
8 35-50 60 Repeat 2 0.31109172398751916 strategy_1
8 35-50 72 New 2 0.20447181867559605 strategy_3
8 35-50 72 Old 0 0.9266165665072099 strategy_1
8 35-50 72 Repeat 3 0.6327657047543338 strategy_1
8 35-50 84 New 2 0.7409970847993361 strategy_3
8 35-50 84 Old 2 0.1186457208955547 strategy_3
8 35-50 84 Repeat 0 0.1524094816383822 strategy_2
8 50-60 12 New 2 0.3387895682663954 strategy_1
8 50-60 12 Old 2 0.6182462740144188 strategy_3
8 50-60 12 Repeat 0 0.7350934682435344 strategy_1
8 50-60 24 New 0 0.01996594991389322 strategy_2
8 50-60 24 Old 1 0.5616979331771 strategy_3
8 50-60 24 Repeat 3 0.007075716675987054 strategy_2
8 50-60 36 New 3 0.8948531352456769 strategy_2
8 50-60 36 Old 2 0.884426217487462 strategy_3
8 50-60 36 Repeat 2 0.44347448185765226 strategy_2
8 50-60 48 New 2 0.49962282937192437 strategy_1
8 50-60 48 Old 0 0.18876086241332812 strategy_2
8 50-60 48 Repeat 1 0.5674654695704483 strategy_3
8 50-60 60 New 0 0.0998219668408149 strategy_2
8 50-60 60 Old 2 0.49072541887142906 strategy_3
8 50-60 60 Repeat 3 0.9187764593836389 strategy_3
8 50-60 72 New 3 0.6528608481921302 strategy_1
8 50-60 72 Old 3 0.8422359860629525 strategy_3
8 50-60 72 Repeat 2 0.10887737855351187 strategy_1
8 50-60 84 New 2 0.6265377505637381 strategy_3
8 50-60 84 Old 3 0.48827013081515647 strategy_2
8 50-60 84 Repeat 3 0.9453816888381501 strategy_3
8 60-90 12 New 1 0.019471136715660697 strategy_1
8 60-90 12 Old 3 0.42444452946475597 strategy_1
8 60-90 12 Repeat 3 0.462866583036618 strategy_2
8 60-90 24 New 2 0.29992682271890003 strategy_1
8 60-90 24 Old 3 0.9057477444823135 strategy_2
8 60-90 24 Repeat 2 0.5438822231057178 strategy_1
8 60-90 36 New 3 0.1126175100913478 strategy_1
8 60-90 36 Old 3 0.21184651365664275 strategy_1
8 60-90 36 Repeat 2 0.9287147842916184 strategy_3
8 60-90 48 New 2 0.2863197375945261 strategy_2
8 60-90 48 Old 0 0.8970231675293099 strategy_2
8 60-90 48 Repeat 3 0.7126046806770878 strategy_3
8 60-90 60 New 1 0.44307666601340845 strategy_1
8 60-90 60 Old 1 0.7455438115952426 strategy_3
8 60-90 60 Repeat 3 0.5095315159798411 strategy_3
8 60-90 72 New 3 0.5889340025936655 strategy_3
8 60-90 72 Old 0 0.4737789984695112 strategy_2
8 60-90 72 Repeat 0 0.2837708674772058 strategy_3
8 60-90 84 New 2 0.8920329161897977 strategy_3
8 60-90 84 Old 0 0.44109189806466 strategy_3
8 60-90 84 Repeat 0 0.981362632152304 strategy_1
8 90-100 12 New 2 0.5221947450851999 strategy_3
8 90-100 12 Old 3 0.11424185751692983 strategy_1
8 90-100 12 Repeat 3 0.8346025069053844 strategy_1
8 90-100 24 New 1 0.10633865760152938 strategy_1
8 90-100 24 Old 1 0.6427120028200962 strategy_1
8 90-100 24 Repeat 2 0.03265654170795751 strategy_2
8 90-100 36 New 1 0.6010123393854924 strategy_2
8 90-100 36 Old 0 0.481757792704511 strategy_1
8 90-100 36 Repeat 0 0.03771447480441359 strategy_1
8 90-100 48 New 2 0.2476916510908217 strategy_1
8 90-100 48 Old 3 0.5418819021918103 strategy_3
8 90-100 48 Repeat 2 0.42744582827653754 strategy_3
8 90-100 60 New 1 0.9579344860855614 strategy_3
8 90-100 60 Old 3 0.9884031637368064 strategy_3
8 90-100 60 Repeat 3 0.8192746516264482 strategy_1
8 90-100 72 New 0 0.6024919110499276 strategy_2
8 90-100 72 Old 1 0.13562240501320555 strategy_1
8 90-100 72 Repeat 2 0.5161840223366518 strategy_3
8 90-100 84 New 2 0.1844445530982125 strategy_1
8 90-100 84 Old 1 0.1945161685497745 strategy_1
8 90-100 84 Repeat 1 0.2506458750661482 strategy_1
from implode_csv import csv_to_nested_dict
from nested_structure import Nested
data = csv_to_nested_dict(
Path("sample_data.csv"),
nesting_keys=["foo", "bar", "baz", "qux"],
result_keys=["a", "b", "c"],
)
model = Nested(**data)
print(model.foo[7].get_bar_range(15).baz[24].qux["New"]) # a=0 b=Decimal('0.5336343397996824') c='strategy_1'
print(model.foo[3].get_bar_range(80).baz[12].qux["Old"]) # a=3 b=Decimal('0.9521579798265745') c='strategy_2'
# test suite:
# - the first entry at foo=1, bar=10-30, baz=12, qux=New
# - the last entry at foo=8, bar=90-100, baz=84, qux=Repeat
# - 1000 consecutive extractions in the middle at foo=4, bar=90-100, baz=84, qux=Old
# - 10 "random" consecutive extractions from
# - foo=1, bar=90-100, baz=12, qux=New
# - foo=2, bar=90-100, baz=12, qux=New
# - foo=3, bar=10-30, baz=12, qux=New
# - foo=3, bar=90-100, baz=12, qux=New
# - foo=4, bar=90-100, baz=12, qux=New
# - foo=5, bar=90-100, baz=12, qux=New
# - foo=6, bar=10-30, baz=12, qux=New
# - foo=6, bar=90-100, baz=12, qux=New
# - foo=7, bar=90-100, baz=12, qux=New
# - foo=8, bar=90-100, baz=12, qux=New
# setup code
read -r -d '' pydantic_setup << EOM
from pathlib import Path
from implode_csv import csv_to_nested_dict
from nested_structure import Nested
data = csv_to_nested_dict(
Path("sample_data.csv"),
["foo", "bar", "baz", "qux"],
["a", "b", "c"]
)
model=Nested(**data)
EOM
read -r -d '' pandas_setup << EOM
import pandas as pd
df = pd.read_csv("sample_data.csv")
df[["bar_a", "bar_b"]] = df["bar"].str.split("-",expand=True).astype(int)
EOM
read -r -d '' littletable_setup << EOM
import littletable as lt
model = lt.csv_import(
"sample_data.csv",
transforms={
"foo": int,
"baz": int,
"a": int,
"b": float,
}
)("model")
model.add_field("bar_min", lambda rec: int(rec.bar.split("-")[0]))
model.add_field("bar_max", lambda rec: int(rec.bar.split("-")[1]))
model.create_index("foo")
model.create_index("baz")
model.create_index("qux")
EOM
read -r -d '' polars_setup << EOM
import polars as pl
df = pl.scan_csv("sample_data.csv").with_columns(
pl.col("bar").str.split("-").list.to_struct(n_field_strategy="max_width")
).unnest("bar").collect().select(
pl.col("foo").cast(pl.Int32),
pl.col("field_0").cast(pl.Int32).alias("bar_a"),
pl.col("field_1").cast(pl.Int32).alias("bar_b"),
pl.col("baz").cast(pl.Int32),
pl.col("qux"),
pl.col("a").cast(pl.Int32),
pl.col("b").cast(pl.Float32),
pl.col("c"),
)
EOM
read -r -d '' duckdb_setup << EOM
import duckdb as ddb
ddb.sql(
"""CREATE OR REPLACE TABLE sample(
foo INT, bar VARCHAR, baz INT, qux VARCHAR,
a INT, b FLOAT, c VARCHAR,
bar_a INT GENERATED ALWAYS AS (split_part(bar, '-', 1)) VIRTUAL,
bar_b INT GENERATED ALWAYS AS (split_part(bar, '-', 2)) VIRTUAL
);"""
)
ddb.sql("INSERT INTO sample SELECT * FROM read_csv('sample.csv', AUTO_DETECT=TRUE);")
EOM
# benchmark code
printf "hashmaps w/ pydantic\n"
python -m timeit -u usec -s "$pydantic_setup" 'model.foo[1].get_bar_range(15).baz[12].qux["New"]'
python -m timeit -u usec -s "$pydantic_setup" 'model.foo[8].get_bar_range(95).baz[84].qux["Repeat"]'
python -m timeit -u usec -s "$pydantic_setup" 'for _ in range(1000): model.foo[4].get_bar_range(95).baz[84].qux["Old"]'
python -m timeit -u usec -s "$pydantic_setup" \
'model.foo[1].get_bar_range(95).baz[12].qux["New"]' \
'model.foo[2].get_bar_range(95).baz[12].qux["New"]' \
'model.foo[3].get_bar_range(15).baz[12].qux["New"]' \
'model.foo[3].get_bar_range(95).baz[12].qux["New"]' \
'model.foo[4].get_bar_range(95).baz[12].qux["New"]' \
'model.foo[5].get_bar_range(95).baz[12].qux["New"]' \
'model.foo[6].get_bar_range(15).baz[12].qux["New"]' \
'model.foo[6].get_bar_range(95).baz[12].qux["New"]' \
'model.foo[7].get_bar_range(95).baz[12].qux["New"]' \
'model.foo[8].get_bar_range(95).baz[12].qux["New"]'
printf "\npandas\n"
python -m timeit -u usec -s "$pandas_setup" 'df[["a", "b", "c"]][(df["foo"] == 1) & (df["bar_a"] <= 15) & (df["bar_b"] > 15) & (df["baz"] == 12) & (df["qux"] == "New")]'
python -m timeit -u usec -s "$pandas_setup" 'df[["a", "b", "c"]][(df["foo"] == 8) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 84) & (df["qux"] == "Repeat")]'
python -m timeit -u usec -s "$pandas_setup" 'for _ in range(1000): df[["a", "b", "c"]][(df["foo"] == 4) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 84) & (df["qux"] == "Old")]'
python -m timeit -u usec -s "$pandas_setup" \
'df[["a", "b", "c"]][(df["foo"] == 1) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 12) & (df["qux"] == "New")]' \
'df[["a", "b", "c"]][(df["foo"] == 2) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 12) & (df["qux"] == "New")]' \
'df[["a", "b", "c"]][(df["foo"] == 3) & (df["bar_a"] <= 15) & (df["bar_b"] > 15) & (df["baz"] == 12) & (df["qux"] == "New")]' \
'df[["a", "b", "c"]][(df["foo"] == 3) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 12) & (df["qux"] == "New")]' \
'df[["a", "b", "c"]][(df["foo"] == 4) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 12) & (df["qux"] == "New")]' \
'df[["a", "b", "c"]][(df["foo"] == 5) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 12) & (df["qux"] == "New")]' \
'df[["a", "b", "c"]][(df["foo"] == 6) & (df["bar_a"] <= 15) & (df["bar_b"] > 15) & (df["baz"] == 12) & (df["qux"] == "New")]' \
'df[["a", "b", "c"]][(df["foo"] == 6) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 12) & (df["qux"] == "New")]' \
'df[["a", "b", "c"]][(df["foo"] == 7) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 12) & (df["qux"] == "New")]' \
'df[["a", "b", "c"]][(df["foo"] == 8) & (df["bar_a"] <= 95) & (df["bar_b"] > 95) & (df["baz"] == 12) & (df["qux"] == "New")]'
printf "\nlittletable\n"
python -m timeit -u usec -s "$littletable_setup" 'model.where(foo=1, baz=12, qux="New").where(lambda rec: rec.bar_min <= 15 < rec.bar_max)[0]'
python -m timeit -u usec -s "$littletable_setup" 'model.where(foo=8, baz=84, qux="Repeat").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]'
python -m timeit -u usec -s "$littletable_setup" 'for _ in range(1000): model.where(foo=4, baz=84, qux="Old").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]'
python -m timeit -u usec -s "$littletable_setup" \
'model.where(foo=1, baz=12, qux="New").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]' \
'model.where(foo=2, baz=12, qux="New").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]' \
'model.where(foo=3, baz=12, qux="New").where(lambda rec: rec.bar_min <= 15 < rec.bar_max)[0]' \
'model.where(foo=3, baz=12, qux="New").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]' \
'model.where(foo=4, baz=12, qux="New").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]' \
'model.where(foo=5, baz=12, qux="New").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]' \
'model.where(foo=6, baz=12, qux="New").where(lambda rec: rec.bar_min <= 15 < rec.bar_max)[0]' \
'model.where(foo=6, baz=12, qux="New").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]' \
'model.where(foo=7, baz=12, qux="New").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]' \
'model.where(foo=8, baz=12, qux="New").where(lambda rec: rec.bar_min <= 95 < rec.bar_max)[0]'
printf "\npolars\n"
python -m timeit -u usec -s "$polars_setup" 'df.filter((pl.col("foo") == 1) & (pl.col("bar_a") <=15) & (pl.col("bar_b") >15) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))'
python -m timeit -u usec -s "$polars_setup" 'df.filter((pl.col("foo") == 8) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 84) & (pl.col("qux") == "Repeat"))'
python -m timeit -u usec -s "$polars_setup" 'for _ in range(1000): df.filter((pl.col("foo") == 4) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 84) & (pl.col("qux") == "Old"))'
python -m timeit -u usec -s "$polars_setup" \
'df.filter((pl.col("foo") == 1) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))' \
'df.filter((pl.col("foo") == 2) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))' \
'df.filter((pl.col("foo") == 3) & (pl.col("bar_a") <=15) & (pl.col("bar_b") >15) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))' \
'df.filter((pl.col("foo") == 3) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))' \
'df.filter((pl.col("foo") == 4) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))' \
'df.filter((pl.col("foo") == 5) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))' \
'df.filter((pl.col("foo") == 6) & (pl.col("bar_a") <=15) & (pl.col("bar_b") >15) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))' \
'df.filter((pl.col("foo") == 6) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))' \
'df.filter((pl.col("foo") == 7) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))' \
'df.filter((pl.col("foo") == 8) & (pl.col("bar_a") <=95) & (pl.col("bar_b") >95) & (pl.col("baz") == 12) & (pl.col("qux") == "New"))'
printf "\nduckdb\n"
python -m timeit -u usec -s "$duckdb_setup" "ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=1 AND bar_a <= 15 AND bar_b > 15 AND baz=12 AND qux='New'\")"
python -m timeit -u usec -s "$duckdb_setup" "ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=8 AND bar_a <= 95 AND bar_b > 95 AND baz=84 AND qux='Repeat'\")"
python -m timeit -u usec -s "$duckdb_setup" "for _ in range(1000): ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=4 AND bar_a <= 95 AND bar_b > 95 AND baz=84 AND qux='Old'\")"
python -m timeit -u usec -s "$duckdb_setup" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=1 AND bar_a <= 95 AND bar_b > 95 AND baz=12 AND qux='New'\")" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=2 AND bar_a <= 95 AND bar_b > 95 AND baz=12 AND qux='New'\")" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=3 AND bar_a <= 15 AND bar_b > 15 AND baz=12 AND qux='New'\")" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=3 AND bar_a <= 95 AND bar_b > 95 AND baz=12 AND qux='New'\")" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=4 AND bar_a <= 95 AND bar_b > 95 AND baz=12 AND qux='New'\")" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=5 AND bar_a <= 95 AND bar_b > 95 AND baz=12 AND qux='New'\")" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=6 AND bar_a <= 15 AND bar_b > 15 AND baz=12 AND qux='New'\")" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=6 AND bar_a <= 95 AND bar_b > 95 AND baz=12 AND qux='New'\")" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=7 AND bar_a <= 95 AND bar_b > 95 AND baz=12 AND qux='New'\")" \
"ddb.sql(\"SELECT a, b, c FROM sample WHERE foo=8 AND bar_a <= 95 AND bar_b > 95 AND baz=12 AND qux='New'\")"
@a-recknagel
Copy link
Author

Or, with pandas,

>>> import pandas as pd
>>> df = pd.read_csv("sample_data.csv ")
>>> df[['bar_a', 'bar_b']] = df['bar'].str.split('-',expand=True).astype(int)
>>> df[["a", "b", "c"]][(df["foo"] == 7) & (df["bar_a"] <= 15) & (df["bar_b"] > 15) & (df["baz"] == 24) & (df["qux"] == "New")]
     a         b           c
759  0  0.533634  strategy_1
>>> df[["a", "b", "c"]][(df["foo"] == 3) & (df["bar_a"] <= 80) & (df["bar_b"] > 80) & (df["baz"] == 12) & (df["qux"] == "Old")]
     a         b           c
337  3  0.952158  strategy_2

@ptmcg
Copy link

ptmcg commented Sep 19, 2023

Using littletable would look like this:

import littletable as lt
from decimal import Decimal

model = lt.csv_import(
    "https://gist.githubusercontent.com/a-recknagel/e7bc969512853866becb8bc90cc093d7/raw/0f5174258c94749beddb33e73656709d4476c161/sample_data.csv",
    transforms={
        **{}.fromkeys("foo baz a".split(), int),
        "b": Decimal,
    }
)("model")

# for range checks
model.add_field("bar_min", lambda rec: int(rec.bar.split("-")[0]))
model.add_field("bar_max", lambda rec: int(rec.bar.split("-")[1]))

print(model.info())
print(model[0])

model.create_index("foo")
model.create_index("baz")
model.create_index("qux")

# each slice is a new littletable Table, so they can be chained together
# the final slice is presented as a pretty output
output_fields = "a b c".split()
model.by.foo[7].where(lambda rec: rec.bar_min <= 15 <= rec.bar_max).by.baz[24].by.qux["New"].present(output_fields)
model.by.foo[3].where(lambda rec: rec.bar_min <= 80 <= rec.bar_max).by.baz[12].by.qux["Old"].present(output_fields)
# or just this
# model.where(foo=3, baz=12, qux="Old").where(lambda rec: rec.bar_min <= 80 <= rec.bar_max).present(output_fields)

model[:5].present()

Prints:

  A   B                    C          
 ─────────────────────────────────────
  0   0.5336343397996824   strategy_1


  A   B                    C          
 ─────────────────────────────────────
  3   0.9521579798265745   strategy_2

  
  Foo   Bar     Baz   Qux      A   B                     C            Bar Min   Bar Max 
 ───────────────────────────────────────────────────────────────────────────────────────
    1   10-30    12   New      0   0.4266724448924709    strategy_1        10        30
    1   10-30    12   Old      3   0.9527535060171675    strategy_3        10        30
    1   10-30    12   Repeat   3   0.546172410319005     strategy_3        10        30
    1   10-30    24   New      0   0.34270197832762583   strategy_2        10        30
    1   10-30    24   Old      1   0.872233130556178     strategy_2        10        30


@a-recknagel
Copy link
Author

a-recknagel commented Sep 20, 2023

Output of bash timings.sh on my machine, with pydantic==2.3.0, pandas==2.1.0, littletable==2.2.3, polars==0.19.3, duckdb==0.8.1, average single access in usec added as comments:

hashmaps w/ pydantic
500000 loops, best of 5: 0.65 usec per loop   # 0.650 
500000 loops, best of 5: 0.832 usec per loop  # 0.832
500 loops, best of 5: 823 usec per loop       # 0.823
50000 loops, best of 5: 7.51 usec per loop    # 0.751

pandas
200 loops, best of 5: 1.12e+03 usec per loop  # 1120
200 loops, best of 5: 1.07e+03 usec per loop  # 1070
1 loop, best of 5: 1.1e+06 usec per loop      # 1100
20 loops, best of 5: 1.09e+04 usec per loop   # 1090

littletable
2000 loops, best of 5: 181 usec per loop      # 181
1000 loops, best of 5: 178 usec per loop      # 178
2 loops, best of 5: 1.82e+05 usec per loop    # 182
200 loops, best of 5: 1.88e+03 usec per loop  # 188

polars
200 loops, best of 5: 1.58e+03 usec per loop  # 1580
200 loops, best of 5: 1.6e+03 usec per loop   # 1600
1 loop, best of 5: 1.63e+06 usec per loop     # 1630
20 loops, best of 5: 1.59e+04 usec per loop   # 1590

duckdb
5000 loops, best of 5: 76.7 usec per loop     # 76.7
5000 loops, best of 5: 77.4 usec per loop     # 77.4
5 loops, best of 5: 7.57e+04 usec per loop    # 75.7
500 loops, best of 5: 767 usec per loop       # 76.7

No noteworthy variance between scenarios for any of the different frameworks, and the hashmap-based approach of the pydantic setup beats the list/array based ones by a fair bit.

@roganjoshp
Copy link

I'm adding this for posterity because I misunderstood the requirement. The following code is useful if you want to minimise I/O. Originally I assumed that you would need to read the CSV on each search, which is much more efficient in polars. So, it doesn't meet your requirement, but I think it's still a useful demo to keep handy.

import pandas as pd
import polars as pl
import timeit


def build_bigger_file(n=100):
    csvs = []
    df = pd.read_csv("sample_data.csv")
    
    for x in range(n):
        csvs.append(df)
    df = pd.concat(csvs)
    df.to_csv("bigger_file.csv", index=False)


def with_pandas(filename):
    df = pd.read_csv(filename)
    df[['bar_a', 'bar_b']] = df['bar'].str.split('-',expand=True).astype(int)
    df = df[["a", "b", "c"]][
        (df["foo"] == 7) 
        & (df["bar_a"] <= 15) 
        & (df["bar_b"] > 15) 
        & (df["baz"] == 24) 
        & (df["qux"] == "New")]
    return df

def with_polars(filename):
    df = (
        pl.scan_csv(filename)
        .with_columns(
            pl.col('bar').str.split('-')
            .arr.to_struct(n_field_strategy="max_width"))
        .unnest("bar")
    )
    df = df.filter(
        (pl.col("foo") == 7) 
        & (pl.col("field_0").cast(pl.Int32) <=15) 
        & (pl.col("field_1").cast(pl.Int32) >15) 
        & (pl.col("baz") == 24) 
        & (pl.col("qux") == "New")
    )
    df = df.collect()
    
    return df
    

if __name__ == '__main__':
    filename = "sample_data.csv"
    print(timeit.timeit(lambda: with_pandas(filename), number=50))
    print(timeit.timeit(lambda: with_polars(filename), number=50))
    
    build_bigger_file()
    
    filename = "bigger_file.csv"
          
    print(timeit.timeit(lambda: with_pandas(filename), number=50))
    print(timeit.timeit(lambda: with_polars(filename), number=50))

Gives the output:

0.09021766704972833
0.059402417042292655
3.7113550830399618
0.35027558298315853

So, polars is drastically faster, and because of scan_csv giving a LazyFrame, can work on files larger than memory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment