Very cool #AGU15 poster on jiu-jitsuing markets against free market fundamentalists to accept climate reality. pic.twitter.com/QAJMU2L8Vf
— Julien Emile-Geay (@el_nino_waves) December 16, 2015
Kirk Dornbush Research Assistantships
Highlight from 2015: Evan Elmore and Martin Van der Linden were the 2015 recipients of the Kirk Dornbush Research…
Posted by Vanderbilt Department of Economics on Facebook Tuesday December 29 2015
School choice in Python
Check out my new Github repository at https://github.com/vanderlindenma/school_choice_python.
It contains code to compute school choice assignments via Deferred and Immediate acceptance, and explanations on how to apply the code to different school choice settings.
The code is based on former code by Jeremy Kun, stable-marriage, (2014), GitHub repository, https://github.com/j2kun/stable-marriages, described in one of Jeremy’s blog posts at http://jeremykun.com/2014/04/02/stable-marriages-and-designing-markets/.
I hope to expand on the code and add more functionalities soon.
Otree : when treatment variables don’t fit into a model field
In oTree, because treatment variables are stored as models, your treatment
variable must fit into one of the field types available in Django (see oTree’s documentation on treatment variables).
In this post I’ll describe a hack to circumvent this limitation. It is kind of ugly but it works for me, and it’s the only way I have found to have lists as treatment variables.
The idea is to first convert your treatment variable into a string
and then convert the string back to its intended format.
To do so, you can use the ast
package.
For instance, if your treatment variable consists in choosing between the
two lists [1,2,3]
and [3,1,2]
at the level of the group, you
would first define a treatment field on the Group
model:
class Group(BaseGroup): # ... treatment = models.CharField()
Then inside the before_subsession_starts
method, you would turn the
chosen list into a string and assign it to treatment
(because
treatment
is a CharField
, it can only be assigned strings)
def before_session_starts(self): for group in self.get_groups(): # Turn the chosen list into a string group.treatment = '%s' %(random.choice([1,2,3],[3,1,2])
Assuming [1,2,3]
was picked, group.treatment
is now a string of the
form '[1,2,3]'
. Thus, you will need to define a method that will
convert the string group.treatment
back to a list whenever
you need it. To do so, first import the package ast
:
# Add the following to the import statements before # class Constants(BaseConstants): import ast
Then define the following method inside the Group
model:
class Group(BaseGroup): # ... def convert_to_list(self): self.treatment = ast.literal_eval(self.treatment)
You can now use your treatment variable as a list by calling
convert_to_list
. For instance, if you want to use your list
in the Decide
page, you could call convert_to_list
inside
the vars_for_template
method inside view.py
:
class Decide(Page): # ... def vars_for_template(self): #... self.group.convert_to_list()
This will make group.treatment
available as a list in the
corresponding template.
Troubleshooting
- Remember to have a look at the doc on treatments from oTree. The example above is for treatments at the group level, and you may need to adapt this according to your needs (e.g. by storing your treatment variable in the
participant.var
of the first player in the group as described in the doc). - One complication with using Django
model.CharField()
is that it may change the encoding of your string from utf-8 or ascii to unicode. If that causes trouble, you may need to redefine yourconvert_to_list
method to something like
class Group(BaseGroup): # ... def convert_to_list(self): if isinstance(self.treatment,str): self.treatment = ast.literal_eval(self.treatment) if isinstance(self.treatment,unicode): self.treatment = ast.literal_eval(self.treatment.encode("utf-8"))
A glance at python’s “tagging” of objects
Just learned the hard way about some basics of python’s memory management. For people coming from R
or other languages, it might be confusing to realize that if you define
x = [1,2,3]
set
x = y
and then modify x, for instance through
x.append(4)
the change in x will propagate to y. This means that if you query the value of y, you will in fact get
[1,2,3,4]
This also means that the sequence
x = [1,2,3] x.append(4)
Is very much different from
x = [1,2,3,4]
For more on this and how to “really” define a new list with some life of its own in the memory, but with the same value as x,
see http://henry.precheur.org/python/copy_list.
Tackling Python’s project structure
I recently started playing with oTree (“a Django-based framework for implementing multiplayer decision strategy games.”) in order to code a school choice experiment. This lead me to dig deeper into Python.
One of the issue I got stuck on is probably the most basic issue of all : how to structure the folder and subfolders containing my Python code?
I was not looking for anything fancy here. The code for oTree experiment is mostly located in a file called model.py
and all I wanted was a way to
- Define the Classes I use in
model.py
in separate files that I could later “import” inmodel.py
, so thatmodel.py
does not become crazy long and unreadable - Group the files in which I define those classes into subfolders so that the folder containing
model.py
does not get overcrowded either. - E.g : because I am coding a school choice experiment, I wanted to have a subfolder containing all the solvers that I use to compute the final assignments based on preferences and priorities, and later import the corresponding classes in
model.py
in order to compute participants’ payoffs.
As basic as this problem may seem, the solution is not obvious (at least to me). Googeling this kind of issues yields a ton of different solutions, and it’s easy to get lost.
The most understandable and functional solution I have found so far is : http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html
If we are to believe the title, this should also be a “Pythonic” solution, which means it should — hopefully — put you at peace with Python aesthetes (from what I understand, “Pythonic” means something like “in the spirit of Python” or “following the coding strandards which are considered good practice by Python’s community”, whatever that may mean).
Two warnings about the solution in the above links:
- Although the solution claims to be “Pythonic”, I’ve often seen people argue against the use of imports of the form
from subpackage import *.
These people usually say that these tend to “clutter the namespace”. The truth is I have no idea what that refers to, so I don’t know whether the argument applies to the use ofimport *
described in the links. Anyways it is good to know thatimport *
can sometimes freak people out, even if — like myself — you don’t quite understand why.
- Suppose that following the solution described in the link, you’ve specified the
__all__
variable in__init__
in thesubpackage
directory , and you runfrom subpackage import *
fromfile2.py
(in thepackage
directory). Now say you want to accessThat_Class
, one of the Classes fromsubmodule2.py
in thesubpackage
directory. Don’t be surprised if callingThat_Class()
fromfile2.py
returns the errorNameError: name 'That_Class' is not defined
. Indeed, you’ve only importedsubmodule2.py
“as a single object”, and not all the Classes it contains individually. Therefore In order to callThat_Class
fromfile2.py,
you will need to usesubmodule2.That_Class()
.
Intuition and visualization for duality in linear programming
I have struggled for a while (years?) with getting some form of intuition for duality results in linear programming. Today I finally found this gem:
http://cstheory.stackexchange.com/q/16206/20762.
In case you want to form some intuition about duality, I couldn’t encourage you enough to carefully read through Neal Young’s comment and Mike Spivey’s answer to the above question on cstheory.stackexchange.
Proofreading your work with Amazon Mturk
How ?
http://groups.csail.mit.edu/uid/deneme/?p=531
What you can hope from it
http://groups.csail.mit.edu/uid/deneme/?p=561
I personally tried it on one of my working papers and was very much satisfied with the value for money/time.
If you are sharing the pages of your paper with the Mturker via a dropbox public folder, you might want to avoid manually copying the public links to each of your pages into the cvs file. If you are using a mac, one way to automate this step is using the Create Dropbox Collection v1.1 service by Brett Terpstra. However, this generates an ordered list of the links, meaning you will still have to manually remove the numbers in front of each link. If you want to skip that last step, see the simple tweak of Create Dropbox Collection I put on the Code section.
The whys and hows of giving up Mendeley and going “all in” with Zotero
Why?
http://thesocietypages.org/cyborgology/2013/01/22/the-mendeley-dilemma/
How?
http://geekandgirliestuff.blogspot.com/2013/03/going-all-in-with-zotero-zotpad-and.html
http://www.hastac.org/blogs/craigeley/2013/02/25/ipad-workflow-zotero-zotfile-zotpad
More
https://github.com/chrisjr/zotero-prevent-duplicates
https://github.com/ZotPlus/zotero-better-bibtex
R : a coercive programming language
I recently got a great answer to a question I asked on economics.stackexchange.com which lead me to explore the matchingMarket R-library, by Thilo Kleins. The library contains very handy functions to compute the outcome of some of the most famous matching algorithm in the college admission literature.
I wanted to tweak the functions a little to use them in a research project but I quickly realized that my knowledge of R was to limited to do that. So I painfully started learning a little more about R and I figured I might as well document some of my quest for R-mastery here. Hopefully, I won’t be completely off all the time and what I write may help someone.
Here is the first important thing that I learned the hard way and which is not always emphasized in introductions to R : R is a coercive programming language. This means that, from time to time, R will “coerce” variables of a certain type (logical, numeric,…) into another type. Suppose for instance that we ask
1 == TRUE
This seems to make no sense : 1 is a numeric, TRUE is a logical, what does it mean to ask whether they are equal? Intuitively, one may expect equality comparisons to only be applicable between numbers, and one might expect
1 == TRUE
to yield an error. Well, it might be so in other languages, but not in R. It is not that R can “really” answer questions like
"apple" == 3.14
But if you ask R to do so, it will still try to see if it cannot, in one way or another, transform (i.e. coerce) the type of “apple” and “3.14” to make them comparable. Back to the first query
1 == TRUE
R knows that TRUE is a logical and that 1 is a numeric. But instead of giving up and returning an error, R will ask “what if I tried to turn ‘TRUE’ into a numeric and performed the equality check anyways”? The R function in charge of trying to turn any argument into a numeric is as.numeric. Thus when sending R the former query, you are in fact asking
1 == as.numeric(TRUE)
Now, somewhat unsurprisingly, R people have decided that
as.numeric(TRUE)=1
Other variables have a defined numeric equivalent. For example, as you might expect,
as.numeric(FALSE)) = 0
Thus to sum up
1 == TRUE
is equivalent to
1 == as.numeric(TRUE)
and therefore in the console
> 1== TRUE [1] TRUE
The last piece of code might seem like nothing, but for someone who starts to learn R, it can be a huge pain to figure out. Now, there is much more to coercion and object types than the little example above. One could for instance ask : “How do we know if R will coerce ‘TRUE’ into a numeric or ‘1’ into a logical”? The short answer can be found in the help of the == operator (” ?`==` ” in the console).
” If the two arguments are atomic vectors of different types, one is coerced to the type of the other, the (decreasing) order of precedence being character, complex, numeric, integer, logical and raw.”
Also, if == was the only operator to coerce variables, it would not be so much of an issue. Things are much more complex however : many other operators and functions do coerce object types.
As a matter of fact, there would be a lot to say (and I still have a lot to learn) about R types and the way R manages coercion. It is not the place — nor am I the right author — to do this. My only goal here was to stress this following simple point :
When dealing with R, one must learn to live with the fact that object types will not always match and that this will not always lead to an error. In an ideal world (?), code would not rely too much on automatic coercion by R and types would be explicitly matched before performing operations. In practice however, code does rely on automatic coercion and if one wants to survive the R world, one must learn about and get used to coercion. At the very top of the list of question one should ask him or herself when one does not understand a piece of code is : “is there any coercion happening which I am not completely comfortable with?”.
To dig deeper, here are a couple of relevant questions on http://stackoverflow.com/:
- http://stackoverflow.com/questions/5681166/what-evaluates-to-true-false-in-r
- http://stackoverflow.com/questions/14932015/why-does-true-true-in-r
- http://stackoverflow.com/questions/6258004/r-types-and-classes-of-variables?lq=1
- http://stackoverflow.com/questions/8855589/a-comprehensive-survey-of-the-types-of-things-in-r-mode-and-class-and-type
- http://stackoverflow.com/questions/27637708/conditional-statement-in-daa-r-of-the-r-matchingmarkets-library