Digital Labor 2014: The Future of Workers in the Sharing Economy

Tom Slee

Bad Reputation

This is an iPython Notebook


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)

The Sharing Economy Today


In [3]:
Peers


Out[3]:

In [4]:
# area, type, location: count, funding, 
peers('location', 'count')

The Airbnb of this...

The Uber of that...

Airbnb

Origin story: Air bed and breakfast

Regular people sharing the home in which they live

Room Types

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.

Single listers and multiple listers

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')


Airbnb: Economical with the truth

  • Most of Airbnb's money comes from whole home/apartment rentals
  • Around half of Airbnb's money comes from people with multiple listings.
  • Airbnb talks about one half of its business to justify the other half.

Rome


In [7]:
Liz


Out[7]:

Gentrification and conflict in Trastevere

From The Guardian:

  • 1956: Cinema America opens
  • 2000 (ish): Cinema America closes.
  • 2004: Owners want to pave it, put up a parking lot (and apartments)
  • November 2012: Occupation
  • September 2014: Eviction

Airbnb in Rome

Rome Map

Uber

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."

The \$90,000 Unicorn

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')


Uber changes

  • Fare cuts
  • \$1 safety fee
  • \$10/week phone rental (August 2014)
  • increase Uber's cut from 20% to 25% (September 2014)
  • Uber strikes (September, October 2014)

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."

Reputation and Trust


In [29]:
Sketch


Out[29]:

Sharing, Reputation, and Trust

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"

Trust and Transaction Costs

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:

  • Regulation and certification: doctors
  • Branding:
  • Group membership, Quakers.
  • Reputation: communities and word of mouth.

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.

Trust, Reputation, and Rating Systems


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]:

UNPLUG NOW


In [71]:
Sketch


Out[71]:

Why implement a useless system?

It's doing two other things:

A denunciation system (signal is to the platform owner)

  • 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.

It's a front for other aspects of the discipline 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.

Platform owners must establish their brand with customers and maintain control over service providers

Ways to think about reputation systems

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.

Do you know about Jian?

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.

The Future: Reputation Society

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:

  • invest in it
  • draw on it

The illusion of control.

Privacy: unravel, as those who are not able to take part lose out.

Forms of Resistance

  • 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 [ ]: