In [3]:
# iPython imports and configuration
from IPython.display import Image
from IPython.display import display
from IPython.display import YouTubeVideo
import logging
import sqlanydb
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
import matplotlib
import seaborn as sns
#%matplotlib inline
# Images and so on
Liz = Image('img/liz_in_trastevere.jpg', width=400, height=400)
Peers = Image('img/peers.png', width=800, height=500)
Sketch = Image('img/sketch.jpg', width=800, height=500)
MitchellCustomerService = YouTubeVideo('_LiDTKEF1ek', width=600)
AirbnbChurnRatings = Image('img/churn_rating.png', width=800, height=600)
# global database connection (Airbnb)
_conn = None
DB_SERVERNAME="dbnb"
DB_NAME="dbnb"
DB_FILE="/home/tom/src/airbnb/db/dbnb.db"
PIECHART_EXPLODE = 0.05
sns.set_context("notebook", font_scale=1.0, rc={"lines.linewidth": 2.5})
logger = logging.getLogger()
def connect():
try:
global _conn
if _conn is None:
_conn = sqlanydb.connect(
userid="dba",
password="sql",
serverName=DB_SERVERNAME,
databasename=DB_NAME,
databasefile=DB_FILE)
return _conn
except:
logger.error(
"Failed to connect to database." +
"You may need to change the DB_FILE value.")
conn = connect()
def bar_plot(result_set, title, xlabel, ylabel):
(labels, y) = ([x for x, y in result_set], [y for x, y in result_set])
x = [labels.index(x) for x, y in result_set]
(width, opacity) = (0.4, 0.5)
plt.xlabel(xlabel)
plt.ylabel(ylabel)
plt.title(title)
plt.bar(x, y, align='center', width=width, alpha=opacity)
plt.xticks(x, labels)
plt.show()
def piechart_plot(result_set, title):
(labels, fractions,) = ([x for x, y in result_set],
[float(y) for x, y in result_set])
explode = [PIECHART_EXPLODE if y < 25 else 0.0 for y in fractions]
plt.title(title, fontsize='x-large', fontweight='bold')
patches, texts, autotexts = plt.pie(fractions,
labels=labels,
explode=explode,
#colors=('lightsteelblue',
# 'lightseagreen',
# 'lightslategray',
# 'lightsalmon',
# 'lightyellow',
# ),
colors=('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'),
shadow=False,
autopct='%1.1f%%',
)
font_properties = fm.FontProperties()
font_properties.set_size('x-large')
plt.setp(autotexts, fontproperties=font_properties)
plt.setp(texts, fontproperties=font_properties)
plt.show()
def room_type_plot(search_area, by_what):
cur = conn.cursor()
sql = """select top 1 survey_description, survey_id
from survey key join search_area where search_area.name = ?
order by survey_id desc"""
cur.execute(sql, (search_area,))
[title, survey_id] = cur.fetchone()
cur.close()
cur = conn.cursor()
sqlpre = "select room_type, "
sqlpost = " from room where survey_id = ? and room_type is not Null group by room_type"
if by_what == 'rooms' or by_what == 'listings':
by_what_insert = 'count(*)'
elif by_what == 'visits':
by_what_insert = 'sum(reviews)'
elif by_what == 'income':
by_what_insert = 'sum(reviews * price)'
else:
by_what_insert = 'count(*)'
sql = sqlpre + by_what_insert + sqlpost
cur.execute(sql, (survey_id,))
rs = cur.fetchall()
cur.close()
(xlabel, ylabel) = ('Room Type', 'Number of Listings')
#bar_plot(rs, title, xlabel, ylabel)
piechart_plot(rs, title)
def city_growth_plot(search_area, by_what):
cur = conn.cursor()
sqlpre = "select survey_date, "
sqlpost = """ from room key join survey
where survey_description like ? || '%'
group by survey_date
order by survey_date"""
if by_what == 'rooms' or by_what == 'listings':
by_what_insert = 'count(*)'
elif by_what == 'visits':
by_what_insert = 'sum(reviews)'
elif by_what == 'income':
by_what_insert = 'sum(reviews * price)'
else:
by_what_insert = 'count(*)'
sql = sqlpre + by_what_insert + sqlpost
cur.execute(sql, (search_area,))
rs = cur.fetchall()
cur.close()
(xlabel, ylabel) = ('Date', 'Count')
bar_plot(rs, search_area, xlabel, ylabel)
#piechart_plot(rs, title)
def multilister_plot(search_area, by_what):
cur = conn.cursor()
sql = """select top 1 survey_description, survey_id
from survey key join search_area
where search_area.name = ?
order by survey_id desc"""
cur.execute(sql, (search_area,))
[title, survey_id] = cur.fetchone()
cur.close()
cur = conn.cursor()
sqlpre = "select if multilister = 1 then 'multi' else 'single' endif, "
sqlpost = " from host where survey_id = ? group by multilister order by multilister"
if by_what == 'hosts':
by_what_insert = 'count(*)'
elif by_what == 'listings':
by_what_insert = 'sum(rooms)'
else:
by_what_insert = 'sum(review_count)'
sql = sqlpre + by_what_insert + sqlpost
cur.execute(sql, (survey_id,))
rs = cur.fetchall()
cur.close()
(xlabel, ylabel) = ('Multilister', by_what)
#bar_plot(rs, title, xlabel, ylabel)
piechart_plot(rs, title)
def rating_plot(search_area):
cur = conn.cursor()
sql = """select top 1 survey_description, survey_id
from survey key join search_area
where search_area.name = ?
order by survey_id desc"""
cur.execute(sql, (search_area,))
[title, survey_id] = cur.fetchone()
cur.close()
cur = conn.cursor()
sql = """select overall_satisfaction r, count(*) n
from room
where survey_id = ?
and r is not null
group by r
order by r"""
cur.execute(sql, (survey_id,))
rs = cur.fetchall()
cur.close()
(xlabel, ylabel) = ('Rating', 'Number')
bar_plot(rs, title, xlabel, ylabel)
# Yelp
_conn_yelp = None
DB_SERVERNAME_YELP="yelp"
DB_NAME_YELP="yelp"
DB_FILE_YELP="/home/tom/src/yelp/yelp.db"
PIECHART_EXPLODE = 0.05
logger = logging.getLogger()
def connect_yelp():
try:
global _conn_yelp
if _conn_yelp is None:
_conn_yelp = sqlanydb.connect(
userid="dba",
password="sql",
serverName=DB_SERVERNAME_YELP,
databasename=DB_NAME_YELP,
databasefile=DB_FILE_YELP)
return _conn_yelp
except:
logger.error(
"Failed to connect to database." +
"You may need to change the DB_FILE_YELP value.")
conn_yelp = connect_yelp()
def yelp_plot(category):
cur = conn_yelp.cursor()
sql = """select stars, count(*) n from
business b key join bus_cat bc key join category c
where c.category = ?
group by stars
order by stars"""
cur.execute(sql, (category,))
rs = cur.fetchall()
cur.close()
title = 'Yelp ratings for ' + category
(xlabel, ylabel) = (category, 'Number')
bar_plot(rs, title, xlabel, ylabel)
#piechart_plot(rs, title)
SQL_AREA_COUNT = """select area, count(*) n
from peers_partner
group by area
order by 2 desc"""
SQL_AREA_FUNDING = """select area, sum(funding_2014) funding
from peers_partner
where funding_2014 is not null
group by area
having funding > 0
order by 2 desc"""
SQL_LOCATION_COUNT = """select location, count(*) n
from peers_partner
group by location
order by 2 desc"""
SQL_LOCATION_FUNDING = """select location, sum(funding_2014) funding
from peers_partner
where funding_2014 is not null
group by location
order by 2 desc"""
SQL_COMMERCIAL_COUNT = """select type, count(*) n
from peers_partner
group by type
order by 2 desc"""
def peers(group_by, value):
if group_by=="area":
if value=="count":
sql = SQL_AREA_COUNT
elif value == "funding":
sql = SQL_AREA_FUNDING
elif group_by== "type":
if value == "count":
sql = SQL_COMMERCIAL_COUNT
elif group_by == "location":
if value == "count":
sql = SQL_LOCATION_COUNT
elif value == "funding":
sql = SQL_LOCATION_FUNDING
cur = conn_yelp.cursor()
cur.execute(sql)
rs = cur.fetchall()
cur.close()
piechart_plot(rs, "peers")
def blablacar_plot():
cur = conn_yelp.cursor()
sql = """select rating as stars, count(*) n from
blablacar
group by stars
order by stars"""
cur.execute(sql)
rs = cur.fetchall()
cur.close()
title = 'Blablacar ratings'
(xlabel, ylabel) = ('Blablacar ratings', 'Number')
bar_plot(rs, title, xlabel, ylabel)
#piechart_plot(rs, title)
def driver_plot(driver_type):
cur = conn_yelp.cursor()
sql = """select entry_type, amount from driver_income
where driver_type = ?"""
cur.execute(sql, (driver_type,))
rs = cur.fetchall()
cur.close()
title = driver_type
piechart_plot(rs, title)
In [3]:
Peers
Out[3]:
In [4]:
# area, type, location: count, funding,
peers('location', 'count')
Enter a city as the first argument and 'listings', 'visits', or 'income' as the second:
In [5]:
# arg0: city.
# arg1: 'listings', 'visits', 'income'
room_type_plot('london', 'income')
Conclusion: The bulk of Airbnb's money comes from whole-home rentals. The talk of local experience is overdone.
The Airbnb messaging highlights "regular people occasionally sharing the home in which they live".
Enter a city for the first argument, and either hosts, listings, or income for the second argument
In [9]:
# hosts, listings, visits, income
multilister_plot('rome', 'income')
In [7]:
Liz
Out[7]:
From The Guardian:
Uber: "the median income on uberX is more than \$90,000 per year per driver in New York and more than \$74,000 per year per driver in San Francisco"
Washington Post: "Uber’s remarkable growth could end the era of poorly paid cab drivers"
CNBC: "Uber’s $90K salary could disrupt the taxi business
Mike Jones, CEO of Science and former CEO of Myspace: "You’re qualified to drive a car, but not professionally doing it. Congratulations, boom, you’re making [a] $90,000-a-year average Uber salary."
Alison Griswold of Slate: "In several months of reporting on Uber, I have yet to come across a single driver earning the equivalent of \$90,766 a year. Those I’ve spoken with report that they gross around \$1,000 a week after commission and sales tax—but before gas and other expenses—for annual income closer to $50,000."
In [8]:
# arg0: 'uber', 'la_taxi', 'sd_taxi' or 'to_taxi'
driver_plot('la_taxi')
Rebecca Harshbarger of the New York Post: "Drivers for UberX — the company’s low-cost, most-used service — make a gross wage of \$36.16 per hour, but **the net payout drops to \$25.17 after the company skims off a 20 percent fee, as well as sales tax and a worker’s- compensation payment to the Black Car Fund, according to the figures released last week.That’s only slightly higher than the average pay of \$24.88 an hour that yellow cabbies take home,** according to the Taxi and Limousine Commission — and **this amount already factors in the highest possible expense of leasing a cab from a garage. Uber’s \$25.17-an-hour net take-home pay doesn’t even factor in the cost of the vehicle or its maintenance.** Neither Uber nor yellow-cab figures include gas, since drivers’ mileage varies widely."
In [29]:
Sketch
Out[29]:
Wired: "How Airbnb and Lyft Finally Got Americans to Trust Each Other"
David Brooks: "Companies like Airbnb establish trust through ratings mechanisms... People in the Airbnb economy don’t have the option of trusting each other on the basis of institutional affiliations, so they do it on the basis of online signaling and peer evaluations."
Thomas Friedman: "Airbnb’s real innovation — a platform of “trust” — where everyone could not only see everyone else’s identity but also rate them as good, bad or indifferent hosts or guests. This meant everyone using the system would pretty quickly develop a relevant “reputation” visible to everyone else in the system."
Brian Chesky: "Cities can’t screen as well as technologies can screen. Companies have these magical things called reputation systems"
Let's stop and think a bit about trust.
What is trust all about? It's a problem of asymmetric information. Trusting a stranger means distinguishing trustworthy people from those who wish to seem trustworthy but are not.
The idea is that we establish trustworthiness by displaying a sign that is affordable for a really trustworthy person and prohibitively costly for an untrustworthy person. In the right conditions this leads to trust by separating equilibrium. If not, then pooling equilibrium.
Examples:
None are perfect solutions. Prejudice. Scarlet Letter.
It's a foundation of Internet thought that low transaction costs makes interactions easier. Yochai Benkler "Wealth of Networks". But this does not apply when the problem is trust. In fact it can make it more difficult because it makes it easier for mimics.
It can work for a while, as there is a self-selecting community. But then it becomes a target for mimics.
In [6]:
# bars, doctors, restaurants, auto repair, hair stylists
yelp_plot('restaurants')
In [4]:
blablacar_plot()
In [2]:
rating_plot('barcelona')
eBay study: Paul Resnick and Richard Zeckhauser
In [99]:
AirbnbChurnRatings
Out[99]:
In [71]:
Sketch
Out[71]:
It's doing two other things:
Platform owners can take action and remove people from the platform if they wish. Another risk that is absorbed by the worker on the platform. Airbnb search results. Uber and Lyft.
The most demanding customers are the most influential. It promotes entitlement.
It builds an environment that demands affective behaviour and emotional labour.
It's a surveillance system.
Gamification: the awarding of points for approved behaviours.
Uber's rules: must take 90% of calls. Don't criticise the company.
Airbnb superhost: must respond within an allotted time.
TaskRabbit: Elite means abide by the policies the company puts out.
It's a measure of conformity to the platform's brand. It's not reputation. It's brownie points.
Alice Marwick/Foucault - self-presentation, personal branding
Arlie Hoschild - emotional labour
James C. Scott - Seeing Like a State. heroic simplification and legibility.
Redefines reputation: peer-to-peer reputation is one thing: reputation as an asset is another.
It's worth remembering what reputation is and how different it is to these systems that are in play.
Melissa Martin, http://www.nothinginwinnipeg.com/2014/10/do-you-know-about-jian/
This is the moment when I first learned. I was 24 years old perhaps — I’m counting back, trying to remember what was then, and when was that — and, after about six years slogging it out in freelance music writing, finally ghosting around the edges of my first fancy industry party. And there was a man gliding towards the bar, wearing the liquid smile that rides the faces of most self-satisfied stars. King of the scene in dark-wash denim jeans.
I turned to an old friend of mine, a man who had logged many years in the music biz. “Isn’t that Jian Ghomeshi?”
He sipped his beer and nodded, but what he said next I had not expected. “Be careful,” he said, with the dark and searching eyes of someone who is holding a story that isn’t theirs to tell.
“Why?”
“Just be careful,” he repeated, darkly. “He’s weird, with women.”
Warned by this, I kept my distance and just watched. I saw the way he moved towards women, introduced himself, and pushed his way into their space. There was something about the way his hands slid over tense and hunched-up shoulders, found their way to the small of a half-turned back, a waist, a hip. Nothing you’d call a crime, not quite. Nothing you could name. Just a sense, all the little things that added up to say — this isn’t safe. This person is not safe.
Boundary issues, call ‘em, and they were persistent. I saw it on other occasions after that, though only a few — other parties, where I’d lean my head against another woman’s so that we could exchange our warnings in the night. Through these other women I started to hear stories, filtering through in little bites: it felt like everyone had a friend with a story. A friend who was was hurt or leered at. A friend who had been uncomfortable, cornered or afraid.
But how could you say that, in a way that would ever be believed? How would you describe that for the world, in a way that the world would ever believe?
So instead, you start to turn to the women around you, and you say: “do you know about Jian?”
And you watch them nod, and pass it on.
Rachel Botsman: "Welcome to the reputation economy, where your online history becomes more powerful than your credit history."
They have big plans, even if they are not yet realized.
Take reputation from one site and use it on another (like personal information, personal commitment, evaluation of you).
Reputation as asset, reputation as currency:
The illusion of control.
Privacy: unravel, as those who are not able to take part lose out.
Section 230 is a problem: allows even less accountability than most market-participants
Employment classification: HandyBook (Kevin Carhart)
The American problem: inability to see a constructive role for city governments.
It is not inevitable, any more than Groupon was inevitable. There are many futures, and city governments can play a part in them: Paris (Velib and Autolib), Sheffield and London with Public Transit and Congestion Pricing.
When things go wrong with city government, as they do... To borrow a line from the civil liberties people, "The solution to bad democracy is more democracy."
In [ ]:
MitchellCustomerService
In [ ]: