Welcome to the Scikit-oTree tutorial. This package aims to integrate any experiment developed on-top of oTree, with the Python Scientific-Stack; alowing the scientists to access a big collection of tools for analyse the experimental data.
import skotree
skotree.VERSION
'0.5'
Scikit-oTree don't preprocess any data from the experiment. All the information are preserved exactly as any traditional export from oTree; the project only take this data and present it.
oTree uses some global configuration to make it run. Scikit-oTree don't store any global configuration alowwing to load data from different experiments without problems. All the oTree related processing always happen in an external process.
The data are always presented as a Pandas DataFrame
To load your experiment you need to provide
the location of the oTree deployment. This is the
same location where the setting.py
lives.
# this load the library
import skotree
# this load the experiment located
# in the directory tests and
experiment = skotree.oTree("./tests")
experiment
<oTree@/home/juan/proyectos/skotree/src/tests>
The previous code make a lot of things in background:
experiment
object.Let's check the result
experiment.settings
<django.conf.Settings at 0x7fb702573ac8>
This is the traditional object that you obtain in any oTree experiment if you write
from django.conf import settings
Now let's check some information about the experiment, for example all the exiting oTree apps.
experiment.lsapps()
['matching_pennies']
or maybe you want to see all the sessiong configured that uses all this apps
experiment.lssessions()
['matching_pennies']
Yikes! the app and the session has the same name. Let's check the full session configuration.
experiment.session_config("matching_pennies")
{'app_sequence': ['matching_pennies'], 'display_name': 'Matching Pennies', 'doc': '', 'mturk_hit_settings': {'description': 'Description for your experiment', 'expiration_hours': 168, 'frame_height': 500, 'keywords': ['bonus', 'study'], 'minutes_allotted_per_assignment': 60, 'preview_template': 'global/MTurkPreview.html', 'qualification_requirements': [], 'title': 'Title for your experiment'}, 'name': 'matching_pennies', 'num_demo_participants': 2, 'participation_fee': 0.0, 'real_world_currency_per_point': 0.0}
Finally you can access any content of the settings object ussing the attribute showed before. For example, maybe you want to see the "currency code"
experiment.settings.REAL_WORLD_CURRENCY_CODE
'USD'
Lets check the oTree server data tab
As you can see 4 kind of data can be exported from any experiment.
This generates one DataFrame with one row per participant, and all rounds are stacjed horizontally. For Scikit-oTree this functionallity are exposed as all_data()
method
all_data = experiment.all_data()
all_data
participant.id_in_session | participant.code | participant.label | participant._is_bot | participant._index_in_pages | participant._max_page_index | participant._current_app_name | participant._round_number | participant._current_page_name | participant.ip_address | ... | matching_pennies.3.player.is_winner | matching_pennies.3.player.payoff | matching_pennies.3.group.id_in_subsession | matching_pennies.3.subsession.round_number | matching_pennies.4.player.id_in_group | matching_pennies.4.player.penny_side | matching_pennies.4.player.is_winner | matching_pennies.4.player.payoff | matching_pennies.4.group.id_in_subsession | matching_pennies.4.subsession.round_number | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | bqkfd73t | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | NaN | 0 | 1 | 3 | 2 | NaN | NaN | 0 | 1 | 4 |
1 | 2 | 5cznwlly | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | NaN | 0 | 1 | 3 | 1 | NaN | NaN | 0 | 1 | 4 |
2 | 1 | 5b8zc5hr | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0.0 | 0 | 1 | 3 | 2 | Tails | 1.0 | 100 | 1 | 4 |
3 | 2 | x1f4ua8y | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 1.0 | 0 | 1 | 3 | 1 | Tails | 0.0 | 0 | 1 | 4 |
4 rows × 49 columns
These data-frame contain a row for each player in the given app. If there are multiple rounds, there will be multiple rows for the same participant. To access this information you need to provide the application name to the method app_data()
data = experiment.app_data("matching_pennies")
data
participant.id_in_session | participant.code | participant.label | participant._is_bot | participant._index_in_pages | participant._max_page_index | participant._current_app_name | participant._round_number | participant._current_page_name | participant.ip_address | ... | player.payoff | group.id_in_subsession | subsession.round_number | session.code | session.label | session.experimenter_name | session.mturk_HITId | session.mturk_HITGroupId | session.comment | session.is_demo | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | bqkfd73t | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 1 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
1 | 2 | 5cznwlly | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 1 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
2 | 1 | bqkfd73t | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 2 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
3 | 2 | 5cznwlly | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 2 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
4 | 1 | bqkfd73t | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 3 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
5 | 2 | 5cznwlly | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 3 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
6 | 1 | bqkfd73t | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 4 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
7 | 2 | 5cznwlly | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 4 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
8 | 1 | 5b8zc5hr | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 1 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
9 | 2 | x1f4ua8y | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 1 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
10 | 1 | 5b8zc5hr | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 2 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
11 | 2 | x1f4ua8y | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 2 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
12 | 1 | 5b8zc5hr | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 3 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
13 | 2 | x1f4ua8y | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 3 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
14 | 1 | 5b8zc5hr | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 100 | 1 | 4 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
15 | 2 | x1f4ua8y | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 4 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
16 rows × 28 columns
With the power of pandas.DataFrame you can easily filter the data
filtered = data[["participant.code", "player.penny_side", "player.payoff"]]
filtered
participant.code | player.penny_side | player.payoff | |
---|---|---|---|
0 | bqkfd73t | NaN | 0 |
1 | 5cznwlly | NaN | 0 |
2 | bqkfd73t | NaN | 0 |
3 | 5cznwlly | NaN | 0 |
4 | bqkfd73t | NaN | 0 |
5 | 5cznwlly | NaN | 0 |
6 | bqkfd73t | NaN | 0 |
7 | 5cznwlly | NaN | 0 |
8 | 5b8zc5hr | Heads | 0 |
9 | x1f4ua8y | Heads | 0 |
10 | 5b8zc5hr | Heads | 0 |
11 | x1f4ua8y | Tails | 0 |
12 | 5b8zc5hr | Heads | 0 |
13 | x1f4ua8y | Tails | 0 |
14 | 5b8zc5hr | Tails | 100 |
15 | x1f4ua8y | Tails | 0 |
Describe the data
filtered.describe()
player.payoff | |
---|---|
count | 16.00 |
mean | 6.25 |
std | 25.00 |
min | 0.00 |
25% | 0.00 |
50% | 0.00 |
75% | 0.00 |
max | 100.00 |
group by participant
group = filtered.groupby("participant.code")
group.describe()
player.payoff | ||||||||
---|---|---|---|---|---|---|---|---|
count | mean | std | min | 25% | 50% | 75% | max | |
participant.code | ||||||||
5b8zc5hr | 4.0 | 25.0 | 50.0 | 0.0 | 0.0 | 0.0 | 25.0 | 100.0 |
5cznwlly | 4.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
bqkfd73t | 4.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
x1f4ua8y | 4.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
or check all the columns availables
data.columns
Index(['participant.id_in_session', 'participant.code', 'participant.label', 'participant._is_bot', 'participant._index_in_pages', 'participant._max_page_index', 'participant._current_app_name', 'participant._round_number', 'participant._current_page_name', 'participant.ip_address', 'participant.time_started', 'participant.visited', 'participant.mturk_worker_id', 'participant.mturk_assignment_id', 'participant.payoff', 'player.id_in_group', 'player.penny_side', 'player.is_winner', 'player.payoff', 'group.id_in_subsession', 'subsession.round_number', 'session.code', 'session.label', 'session.experimenter_name', 'session.mturk_HITId', 'session.mturk_HITGroupId', 'session.comment', 'session.is_demo'], dtype='object')
tspent = experiment.time_spent()
tspent
session_id | participant__id_in_session | participant__code | page_index | app_name | page_name | time_stamp | seconds_on_page | subsession_pk | auto_submitted | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 2 | 1 | 5b8zc5hr | 1 | matching_pennies | Choice | 1509514681 | 4 | 5 | False |
1 | 2 | 1 | 5b8zc5hr | 2 | matching_pennies | ResultsWaitPage | 1509514686 | 5 | 5 | False |
2 | 2 | 1 | 5b8zc5hr | 4 | matching_pennies | Choice | 1509514692 | 6 | 6 | False |
3 | 2 | 1 | 5b8zc5hr | 5 | matching_pennies | ResultsWaitPage | 1509514693 | 1 | 6 | False |
4 | 2 | 1 | 5b8zc5hr | 7 | matching_pennies | Choice | 1509514696 | 3 | 7 | False |
5 | 2 | 1 | 5b8zc5hr | 8 | matching_pennies | ResultsWaitPage | 1509514701 | 5 | 7 | False |
6 | 2 | 1 | 5b8zc5hr | 10 | matching_pennies | Choice | 1509514706 | 5 | 8 | False |
7 | 2 | 1 | 5b8zc5hr | 11 | matching_pennies | ResultsWaitPage | 1509514707 | 1 | 8 | False |
8 | 2 | 2 | x1f4ua8y | 1 | matching_pennies | Choice | 1509514685 | 7 | 5 | False |
9 | 2 | 2 | x1f4ua8y | 2 | matching_pennies | ResultsWaitPage | 1509514685 | 0 | 5 | False |
10 | 2 | 2 | x1f4ua8y | 4 | matching_pennies | Choice | 1509514689 | 4 | 6 | False |
11 | 2 | 2 | x1f4ua8y | 5 | matching_pennies | ResultsWaitPage | 1509514694 | 5 | 6 | False |
12 | 2 | 2 | x1f4ua8y | 7 | matching_pennies | Choice | 1509514699 | 5 | 7 | False |
13 | 2 | 2 | x1f4ua8y | 8 | matching_pennies | ResultsWaitPage | 1509514700 | 1 | 7 | False |
14 | 2 | 2 | x1f4ua8y | 10 | matching_pennies | Choice | 1509514702 | 2 | 8 | False |
15 | 2 | 2 | x1f4ua8y | 11 | matching_pennies | ResultsWaitPage | 1509514707 | 5 | 8 | False |
# check the available columns
tspent.columns
Index(['session_id', 'participant__id_in_session', 'participant__code', 'page_index', 'app_name', 'page_name', 'time_stamp', 'seconds_on_page', 'subsession_pk', 'auto_submitted'], dtype='object')
# filter only the most important columns
tspent = tspent[["participant__code", "page_index", "seconds_on_page"]]
tspent
participant__code | page_index | seconds_on_page | |
---|---|---|---|
0 | 5b8zc5hr | 1 | 4 |
1 | 5b8zc5hr | 2 | 5 |
2 | 5b8zc5hr | 4 | 6 |
3 | 5b8zc5hr | 5 | 1 |
4 | 5b8zc5hr | 7 | 3 |
5 | 5b8zc5hr | 8 | 5 |
6 | 5b8zc5hr | 10 | 5 |
7 | 5b8zc5hr | 11 | 1 |
8 | x1f4ua8y | 1 | 7 |
9 | x1f4ua8y | 2 | 0 |
10 | x1f4ua8y | 4 | 4 |
11 | x1f4ua8y | 5 | 5 |
12 | x1f4ua8y | 7 | 5 |
13 | x1f4ua8y | 8 | 1 |
14 | x1f4ua8y | 10 | 2 |
15 | x1f4ua8y | 11 | 5 |
# lets describe the time expent by page
tspent.groupby("page_index").describe()
seconds_on_page | ||||||||
---|---|---|---|---|---|---|---|---|
count | mean | std | min | 25% | 50% | 75% | max | |
page_index | ||||||||
1 | 2.0 | 5.5 | 2.121320 | 4.0 | 4.75 | 5.5 | 6.25 | 7.0 |
2 | 2.0 | 2.5 | 3.535534 | 0.0 | 1.25 | 2.5 | 3.75 | 5.0 |
4 | 2.0 | 5.0 | 1.414214 | 4.0 | 4.50 | 5.0 | 5.50 | 6.0 |
5 | 2.0 | 3.0 | 2.828427 | 1.0 | 2.00 | 3.0 | 4.00 | 5.0 |
7 | 2.0 | 4.0 | 1.414214 | 3.0 | 3.50 | 4.0 | 4.50 | 5.0 |
8 | 2.0 | 3.0 | 2.828427 | 1.0 | 2.00 | 3.0 | 4.00 | 5.0 |
10 | 2.0 | 3.5 | 2.121320 | 2.0 | 2.75 | 3.5 | 4.25 | 5.0 |
11 | 2.0 | 3.0 | 2.828427 | 1.0 | 2.00 | 3.0 | 4.00 | 5.0 |
# and lets make a plot but grouped by participant
%matplotlib inline
tspent.groupby("participant__code")[["seconds_on_page"]].plot();
Scikit-oTree offers out of the box the posibility to run the oTree bot-based-tests and retrieve all the data generated by them.
The method bot_data()
consume two arguments:
And the return a dict like object (called CSVStorage
) whith the same attributes as application has the session in the app_sequence
key.
storage = experiment.bot_data("matching_pennies", 4)
storage
Running bots, please wait... [INFO|2017-11-01 05:38:44,513] skotree > Running bots, please wait...
<CSVStore({matching_pennies})>
as you can see the only available app (as we see before) is the matching_pennies
.
Lets extract the data
storage["matching_pennies"]
participant.id_in_session | participant.code | participant.label | participant._is_bot | participant._index_in_pages | participant._max_page_index | participant._current_app_name | participant._round_number | participant._current_page_name | participant.ip_address | ... | player.payoff | group.id_in_subsession | subsession.round_number | session.code | session.label | session.experimenter_name | session.mturk_HITId | session.mturk_HITGroupId | session.comment | session.is_demo | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | n66opzy5 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 1 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
1 | 2 | hjvqfo1o | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 1 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
2 | 3 | gq6vxupy | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 1 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
3 | 4 | x80f6pv3 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 1 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
4 | 1 | n66opzy5 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 2 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
5 | 2 | hjvqfo1o | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 2 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
6 | 3 | gq6vxupy | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 2 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
7 | 4 | x80f6pv3 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 2 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
8 | 1 | n66opzy5 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 100 | 1 | 3 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
9 | 2 | hjvqfo1o | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 3 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
10 | 3 | gq6vxupy | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 100 | 2 | 3 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
11 | 4 | x80f6pv3 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 3 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
12 | 1 | n66opzy5 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 4 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
13 | 2 | hjvqfo1o | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 4 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
14 | 3 | gq6vxupy | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 4 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
15 | 4 | x80f6pv3 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 4 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
16 rows × 28 columns
also for convenience the sintax storage.matching_pennied
are available
storage.matching_pennies
participant.id_in_session | participant.code | participant.label | participant._is_bot | participant._index_in_pages | participant._max_page_index | participant._current_app_name | participant._round_number | participant._current_page_name | participant.ip_address | ... | player.payoff | group.id_in_subsession | subsession.round_number | session.code | session.label | session.experimenter_name | session.mturk_HITId | session.mturk_HITGroupId | session.comment | session.is_demo | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | n66opzy5 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 1 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
1 | 2 | hjvqfo1o | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 1 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
2 | 3 | gq6vxupy | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 1 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
3 | 4 | x80f6pv3 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 1 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
4 | 1 | n66opzy5 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 2 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
5 | 2 | hjvqfo1o | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 2 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
6 | 3 | gq6vxupy | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 2 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
7 | 4 | x80f6pv3 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 2 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
8 | 1 | n66opzy5 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 100 | 1 | 3 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
9 | 2 | hjvqfo1o | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 3 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
10 | 3 | gq6vxupy | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 100 | 2 | 3 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
11 | 4 | x80f6pv3 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 3 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
12 | 1 | n66opzy5 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 4 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
13 | 2 | hjvqfo1o | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 4 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
14 | 3 | gq6vxupy | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 4 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
15 | 4 | x80f6pv3 | NaN | 1 | 12 | 12 | matching_pennies | 4 | ResultsSummary | 127.0.0.1 | ... | 0 | 2 | 4 | fiezcoi1 | NaN | NaN | NaN | NaN | NaN | 0 |
16 rows × 28 columns
If for some reason the experiment fails, this method returns an exception. for example if we provide a invalid number of participants
experiment.bot_data("matching_pennies", 1)
Running bots, please wait... [INFO|2017-11-01 05:38:46,546] skotree > Running bots, please wait...
---------------------------------------------------------------- RuntimeError Traceback (most recent call last) <ipython-input-22-7eb7fed99fee> in <module>() ----> 1 experiment.bot_data("matching_pennies", 1) ~/proyectos/skotree/src/skotree.py in bot_data(self, session_name, num_participants) 689 690 """ --> 691 return self._middleware.bot_data(session_name, num_participants) 692 693 @property ~/proyectos/skotree/src/skotree.py in bot_data(self, session_name, num_participants) 399 return fps 400 --> 401 fps = self.execute(_bot_data) 402 store = CSVStore(fps) 403 return store ~/proyectos/skotree/src/skotree.py in execute(self, func) 262 if isinstance(result, BaseException): 263 logger.debug("Remote procees raises an exception!") --> 264 raise result 265 return result 266 RuntimeError:
To connect to a remote oTree location instead of given the settings.py
path, you need to
provide the URL where the experiment is running.
remote = skotree.oTree("http://localhost:8000")
remote
<oTree@http://localhost:8000>
remote.lsapps()
['matching_pennies']
remote.lssessions()
['matching_pennies']
remote.app_data("matching_pennies")
participant.id_in_session | participant.code | participant.label | participant._is_bot | participant._index_in_pages | participant._max_page_index | participant._current_app_name | participant._round_number | participant._current_page_name | participant.ip_address | ... | player.payoff | group.id_in_subsession | subsession.round_number | session.code | session.label | session.experimenter_name | session.mturk_HITId | session.mturk_HITGroupId | session.comment | session.is_demo | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | bqkfd73t | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 1 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
1 | 2 | 5cznwlly | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 1 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
2 | 1 | bqkfd73t | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 2 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
3 | 2 | 5cznwlly | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 2 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
4 | 1 | bqkfd73t | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 3 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
5 | 2 | 5cznwlly | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 3 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
6 | 1 | bqkfd73t | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 4 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
7 | 2 | 5cznwlly | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | 0 | 1 | 4 | nvnpimbf | NaN | NaN | NaN | NaN | NaN | 0 |
8 | 1 | 5b8zc5hr | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 1 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
9 | 2 | x1f4ua8y | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 1 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
10 | 1 | 5b8zc5hr | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 2 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
11 | 2 | x1f4ua8y | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 2 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
12 | 1 | 5b8zc5hr | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 3 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
13 | 2 | x1f4ua8y | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 3 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
14 | 1 | 5b8zc5hr | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 100 | 1 | 4 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
15 | 2 | x1f4ua8y | NaN | 0 | 12 | 12 | matching_pennies | 4.0 | ResultsSummary | 127.0.0.1 | ... | 0 | 1 | 4 | gh84ltgl | NaN | NaN | NaN | NaN | NaN | 1 |
16 rows × 28 columns
If you are trying to connect to server in auth level mode DEMO
or STUDY
(More Information about modes) without credentials an error will be shown:
skotree.oTree("http://localhost:9000")
---------------------------------------------------------------- NoLoggedin Traceback (most recent call last) <ipython-input-3-6b6d5c6c3e94> in <module>() ----> 1 skotree.oTree("http://localhost:9000") ~/proyectos/skotree/src/skotree.py in __init__(self, path, middleware, **kwargs) 596 middleware = "remote" if is_url(path) else "local" 597 self._path = os.path.abspath(path) if middleware == "local" else path --> 598 self._middleware = MIDDLEWARES[middleware](self._path, **kwargs) 599 600 def __repr__(self): ~/proyectos/skotree/src/skotree.py in __init__(self, url, **kwargs) 426 self._client = requests.session() 427 self.login(**kwargs) --> 428 self.check_loggedin() 429 430 def absurl(self, subpath): ~/proyectos/skotree/src/skotree.py in check_loggedin(self) 458 if "/accounts/login/?next=" in resp.url: 459 msg = "You are not authenticated in experiment located at {}" --> 460 raise NoLoggedin(msg.format(self._url)) 461 462 def lsapps(self): NoLoggedin: You are not authenticated in experiment located at http://localhost:9000
In this cases you need to provide the parameters username
and password
# the credential are not stored internally
exp = skotree.oTree("http://localhost:9000", username="admin", password="skotree")
exp
<oTree@http://localhost:9000>
and now all works as before
exp.all_data()
participant.id_in_session | participant.code | participant.label | participant._is_bot | participant._index_in_pages | participant._max_page_index | participant._current_app_name | participant._round_number | participant._current_page_name | participant.ip_address | ... | matching_pennies.3.player.is_winner | matching_pennies.3.player.payoff | matching_pennies.3.group.id_in_subsession | matching_pennies.3.subsession.round_number | matching_pennies.4.player.id_in_group | matching_pennies.4.player.penny_side | matching_pennies.4.player.is_winner | matching_pennies.4.player.payoff | matching_pennies.4.group.id_in_subsession | matching_pennies.4.subsession.round_number | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | wxcd26g1 | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | NaN | 0 | 1 | 3 | 2 | NaN | NaN | 0 | 1 | 4 |
1 | 2 | akfa88o8 | NaN | 0 | 0 | 12 | NaN | NaN | NaN | NaN | ... | NaN | 0 | 1 | 3 | 1 | NaN | NaN | 0 | 1 | 4 |
2 rows × 49 columns
session_config()
bot_data()
Raises an NotImplementedError
when are called.
remote.bot_data("matching_pennies", 1)
---------------------------------------------------------------- NotImplementedError Traceback (most recent call last) <ipython-input-27-1dbb6d4fbd98> in <module>() ----> 1 remote.bot_data("matching_pennies", 1) ~/proyectos/skotree/src/skotree.py in bot_data(self, session_name, num_participants) 689 690 """ --> 691 return self._middleware.bot_data(session_name, num_participants) 692 693 @property ~/proyectos/skotree/src/skotree.py in bot_data(self, session_name, num_participants) 501 502 def bot_data(self, session_name, num_participants=None): --> 503 raise NotImplementedError("Remote oTree can't run bots") 504 505 @property NotImplementedError: Remote oTree can't run bots
Also the settings attribute always returns None
The pandas.DataFrame itself is a great tool for data analysis, but also can be easily adapted to feed a lot of libraries like: