Skip to content

Commit ae21652

Browse files
authored
Merge pull request #707 from drvinceknight/701
Add summary method to result set
2 parents d6e9b7e + 82bf462 commit ae21652

File tree

4 files changed

+119
-1
lines changed

4 files changed

+119
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ Axelrod.egg-info
1111
basic_strategies.csv
1212
cache.txt
1313
test.csv
14+
summary.csv
1415
basic_tournament.csv

axelrod/result_set.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import csv
22
import tqdm
33

4+
from collections import namedtuple
45
from numpy import mean, nanmedian, std
56

67
from . import eigen
@@ -696,6 +697,53 @@ def __eq__(self, other):
696697
def __ne__(self, other):
697698
return not self.__eq__(other)
698699

700+
def summarise(self):
701+
"""
702+
Obtain summary of performance of each strategy:
703+
ordered by rank, including median normalised score and cooperation
704+
rating.
705+
706+
Output
707+
------
708+
709+
A list of the form:
710+
711+
[[player name, median score, cooperation_rating],...]
712+
713+
"""
714+
715+
median_scores = map(nanmedian, self.normalised_scores)
716+
median_wins = map(nanmedian, self.wins)
717+
718+
self.player = namedtuple("Player", ["Rank", "Name", "Median_score",
719+
"Cooperation_rating", "Wins"])
720+
721+
summary_data = [perf for perf in zip(self.players,
722+
median_scores,
723+
self.cooperating_rating,
724+
median_wins)]
725+
summary_data = [self.player(rank, *summary_data[i]) for
726+
rank, i in enumerate(self.ranking)]
727+
728+
return summary_data
729+
730+
def write_summary(self, filename):
731+
"""
732+
Write a csv file containing summary data of the results of the form:
733+
734+
"Rank", "Name", "Median-score-per-turn", "Cooperation-rating"
735+
736+
Parameters
737+
----------
738+
filename : a filepath to which to write the data
739+
"""
740+
summary_data = self.summarise()
741+
with open(filename, 'w') as csvfile:
742+
writer = csv.writer(csvfile)
743+
writer.writerow(self.player._fields)
744+
for player in summary_data:
745+
writer.writerow(player)
746+
699747

700748
class ResultSetFromFile(ResultSet):
701749
"""

axelrod/tests/unit/test_resultset.py

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import axelrod
33
import axelrod.interaction_utils as iu
44

5-
from numpy import mean, std
5+
from numpy import mean, std, nanmedian
66

77
import tempfile
8+
import csv
89

910
from hypothesis import given, settings
1011
from axelrod.tests.property import tournaments, prob_end_tournaments
@@ -384,6 +385,46 @@ def test_equality(self):
384385
results = tournament.play()
385386
self.assertNotEqual(results, rs_sets[0])
386387

388+
def test_summarise(self):
389+
rs = axelrod.ResultSet(self.players, self.interactions,
390+
progress_bar=False)
391+
sd = rs.summarise()
392+
393+
self.assertEqual(len(sd), len(rs.players))
394+
self.assertEqual([str(player.Name) for player in sd], rs.ranked_names)
395+
self.assertEqual([int(player.Rank) for player in sd],
396+
list(range(len(self.players))))
397+
398+
ranked_median_scores = [list(map(nanmedian, rs.normalised_scores))[i]
399+
for i in rs.ranking]
400+
self.assertEqual([float(player.Median_score) for player in sd],
401+
ranked_median_scores)
402+
403+
ranked_cooperation_rating = [rs.cooperating_rating[i]
404+
for i in rs.ranking]
405+
self.assertEqual([float(player.Cooperation_rating) for player in sd],
406+
ranked_cooperation_rating)
407+
408+
ranked_median_wins = [nanmedian(rs.wins[i]) for i in rs.ranking]
409+
self.assertEqual([float(player.Wins) for player in sd],
410+
ranked_median_wins)
411+
412+
def test_write_summary(self):
413+
tmp_file = tempfile.NamedTemporaryFile()
414+
rs = axelrod.ResultSet(self.players, self.interactions,
415+
progress_bar=False)
416+
rs.write_summary(filename=tmp_file.name)
417+
with open(tmp_file.name, "r") as csvfile:
418+
ranked_names = []
419+
csvreader = csv.reader(csvfile)
420+
for row in csvreader:
421+
ranked_names.append(row[1])
422+
self.assertEqual(len(row), 5)
423+
self.assertEqual(ranked_names[0], "Name")
424+
self.assertEqual(ranked_names[1:], rs.ranked_names)
425+
426+
427+
387428

388429
class TestResultSetFromFile(unittest.TestCase):
389430
tmp_file = tempfile.NamedTemporaryFile(mode='w', delete=False)

docs/tutorials/getting_started/tournament_results.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,3 +233,31 @@ of the cooperation rating::
233233
[0.57..., 0.0, 0.57..., 0.57...]
234234

235235
For more information about these see :ref:`morality-metrics`.
236+
237+
Summarising a tournament
238+
------------------------
239+
240+
The results set can also return a list of named tuples, ordered by strategy rank
241+
that summarises the results of the tournament::
242+
243+
>>> summary = results.summarise()
244+
>>> pprint.pprint(summary)
245+
[Player(Rank=0, Name='Defector', Median_score=2.6..., Cooperation_rating=0.0, Wins=3.0),
246+
Player(Rank=1, Name='Tit For Tat', Median_score=2.3..., Cooperation_rating=0.7, Wins=0.0),
247+
Player(Rank=2, Name='Grudger', Median_score=2.3..., Cooperation_rating=0.7, Wins=0.0),
248+
Player(Rank=3, Name='Cooperator', Median_score=2.0..., Cooperation_rating=1.0, Wins=0.0)]
249+
250+
It is also possible to write this data directly to a csv file using the
251+
`write_summary` method::
252+
253+
>>> results.write_summary('summary.csv')
254+
>>> import csv
255+
>>> with open('summary.csv', 'r') as outfile:
256+
... csvreader = csv.reader(outfile)
257+
... for row in csvreader:
258+
... print(row)
259+
['Rank', 'Name', 'Median_score', 'Cooperation_rating', 'Wins']
260+
['0', 'Defector', '2.6...', '0.0', '3.0']
261+
['1', 'Tit For Tat', '2.3...', '0.7', '0.0']
262+
['2', 'Grudger', '2.3...', '0.7', '0.0']
263+
['3', 'Cooperator', '2.0...', '1.0', '0.0']

0 commit comments

Comments
 (0)