How can I create a 2-way table in python? I have 2 categorical variables in a data set and would like to look at the relationship between the 2 variables by creating a 2-way table. Thank you.
-
Possible Duplicate stackoverflow.com/questions/6129693/python-creating-a-tableCody Piersall– Cody Piersall2013-06-19 21:19:45 +00:00Commented Jun 19, 2013 at 21:19
-
3Do you mean a bidirectional map?brice– brice2013-06-19 21:21:16 +00:00Commented Jun 19, 2013 at 21:21
-
5Can you give us a sample data set?rickcnagy– rickcnagy2013-06-19 21:21:21 +00:00Commented Jun 19, 2013 at 21:21
-
will creating two dictionaries, each one the opposite of the other, i.e. the key in one is the value in the other solve your problem?Fredrik Pihl– Fredrik Pihl2013-06-19 21:32:41 +00:00Commented Jun 19, 2013 at 21:32
-
I thought it was obvious what you wanted, but I was obviously wrong. Can you please elaborate on what you mean by "two-way table"? Do you mean a table where you look up a value by row and column, or a bidirectional mapping as brice suggested?Henry Keiter– Henry Keiter2013-06-19 21:34:34 +00:00Commented Jun 19, 2013 at 21:34
6 Answers
There's a bidict package:
>>> from bidict import bidict
>>> husbands2wives = bidict({'john': 'jackie'})
>>> husbands2wives['john'] # the forward mapping is just like with dict
'jackie'
>>> husbands2wives[:'jackie'] # use slice for the inverse mapping
'john'
You can install it using pip install bidict.
EDIT: For your actual problem - if I understand you correctly - I would use pandas:
# data.csv
Gender Height GPA HS GPA Seat WtFeel Cheat
Female 64 2.60 2.63 M AboutRt No 1
Male 69 2.70 3.72 M AboutRt No 2
Female 66 3.00 3.44 F AboutRt No 3
Female 63 3.11 2.73 F AboutRt No 4
Male 72 3.40 2.35 B OverWt No 0
In [1]: import pandas as pd
In [2]: df = pd.read_csv('data.csv', sep = '\s')
In [3]: grouped = df.groupby(['Gender', 'Seat'])
In [4]: grouped.size()
Out[4]:
Gender Seat
Female AboutRt 3
Male AboutRt 1
OverWt 1
dtype: int64
5 Comments
pandas. Added an example...Probably the best solution in the standard library, if your data is moderately large, is to use sqlite, the in-memory database: http://docs.python.org/2/library/sqlite3.html
Comments
Assuming you don't have to do any interpolation, you can use a dictionary. Use (x, y) tuples as the keys, and whatever your values are as the values. For instance, a trivial 2x2 table like this:
___0___1___
0 | 0 0.5
1 | 0.5 1
Would look like this in code:
two_way_lookup = {
(0, 0) : 0,
(0, 1) : 0.5,
(1, 0) : 0.5,
(1, 1) : 1
}
print(two_way_lookup.get((0, 1))) # prints 0.5
5 Comments
x and y to get a value representing something about that combination of elements." It is not, at least in my mind, the same thing as 2-way lookup, where key/value pairs can be used in either direction.You can create something like a two-level dict (that is, a dict which comprehends two dicts that map the same data in reverse order:
>>> mappings=[(0, 6), (1, 7), (2, 8), (3, 9), (4, 10)]
>>> view = dict(view1=dict(mappings), view2=dict(reversed(k) for k in mappings))
>>> view
{'view2': {8: 2, 9: 3, 10: 4, 6: 0, 7: 1},
'view1': {0: 6, 1: 7, 2: 8, 3: 9, 4: 10}}
1 Comment
If you want a home-brewed, wonky solution, you could do something like this:
import collections
class BDMap:
def __init__(self):
self.x_table = {}
self.y_table = {}
def get(self, x = None, y = None):
if (x != None) and (y != None):
y_vals = self.x_table[x]
if (y in y_vals):
return (x, y)
elif x != None:
return self.x_table[x]
elif y != None:
return self.y_table[y]
def set(self, x, y):
if isinstance(x, collections.Hashable) and isinstance(y, collections.Hashable):
self.x_table[x] = self.x_table.get(x, list()) + [y]
self.y_table[y] = self.y_table.get(y, list()) + [x]
else:
raise TypeError("unhashable type")
For anything other than a one-off script with a small data set, you're undoubtedly better off with one of approaches mentioned, though :)