Finding Profitable Mobile Apps - Analyzing Google Play and the App Store Market

In this project, we will assume a role of data analysis for a company that develops free to download mobile applications. Our goal is to find what kind of app attracts more user for Google Play and the App Store.

We will be using these following data sets:

  • Data set containing data for about 10,000 apps from Google Play. This data was collected in August 2018.
  • Data set containing data for about 7,000 apps from the App Store. This data was collected in July 2017.

Reading the data

Let's begin by first, opening the two data sets.

In [1]:
from csv import reader
        
# App Store data
app_store_file = open('AppleStore.csv', encoding='utf8')
read_app_store_file = reader(app_store_file)
apps_store_data = list(read_app_store_file)
apps_store_header = apps_store_data[0]
apps_store_data = apps_store_data[1:]

# Google Play Store data
google_play_store_file = open('googleplaystore.csv', encoding='utf8')
read_google_play_file = reader(google_play_store_file)
google_play_data = list(read_google_play_file)
google_play_header = google_play_data[0]
google_play_data = google_play_data[1:]

Then, we create a function named explore_data() to make our more readable. Also, we can either show or hide the number of rows and columns of the data set.

In [2]:
def explore_data(dataset, start, end, rows_and_columns=False):
    dataset_slice = dataset[start:end]    
    for row in dataset_slice:
        print(row)
        print('\n') # adds a new (empty) line after each row

    if rows_and_columns:
        print('Number of rows:', len(dataset))
        print('Number of columns:', len(dataset[0]))

Now, we will start using our defined function. Let's start with the google play data set:

In [3]:
print(google_play_header, "\n")
explore_data(google_play_data, 0, 3, True)
['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type', 'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver', 'Android Ver'] 

['Photo Editor & Candy Camera & Grid & ScrapBook', 'ART_AND_DESIGN', '4.1', '159', '19M', '10,000+', 'Free', '0', 'Everyone', 'Art & Design', 'January 7, 2018', '1.0.0', '4.0.3 and up']


['Coloring book moana', 'ART_AND_DESIGN', '3.9', '967', '14M', '500,000+', 'Free', '0', 'Everyone', 'Art & Design;Pretend Play', 'January 15, 2018', '2.0.0', '4.0.3 and up']


['U Launcher Lite – FREE Live Cool Themes, Hide Apps', 'ART_AND_DESIGN', '4.7', '87510', '8.7M', '5,000,000+', 'Free', '0', 'Everyone', 'Art & Design', 'August 1, 2018', '1.2.4', '4.0.3 and up']


Number of rows: 10841
Number of columns: 13

We see that Google Play data set has 10,841 apps and 13 columns. If we look at the headers, we see columns that might help with our analysis are App, Category, Reviews, Installs, Type, Price, and Genres.

In [4]:
print(apps_store_header, "\n")
explore_data(apps_store_data, 0, 3, True)
['id', 'track_name', 'size_bytes', 'currency', 'price', 'rating_count_tot', 'rating_count_ver', 'user_rating', 'user_rating_ver', 'ver', 'cont_rating', 'prime_genre', 'sup_devices.num', 'ipadSc_urls.num', 'lang.num', 'vpp_lic'] 

['284882215', 'Facebook', '389879808', 'USD', '0.0', '2974676', '212', '3.5', '3.5', '95.0', '4+', 'Social Networking', '37', '1', '29', '1']


['389801252', 'Instagram', '113954816', 'USD', '0.0', '2161558', '1289', '4.5', '4.0', '10.23', '12+', 'Photo & Video', '37', '0', '29', '1']


['529479190', 'Clash of Clans', '116476928', 'USD', '0.0', '2130805', '579', '4.5', '4.5', '9.24.12', '9+', 'Games', '38', '5', '18', '1']


Number of rows: 7197
Number of columns: 16

We have 7,197 apps for the App Store data set and 16 columns. The headers we find useful are track_name, price, rating_count_tot, user_rating and prime_genre

Data Cleaning

Before to start our analysis we first need clean thoroughly our data.

Removing Invalid Data

If we check the discussions from our Google Play set source, we can see one of the discussion is saying that row index 10472 has a missing Category header. Let's print the row to confirm.

In [5]:
print(google_play_data[10472])  # incorrect row
print('\n')
print(google_play_header)       # complete header
print('\n')
print(google_play_data[0])      # correct row
['Life Made WI-Fi Touchscreen Photo Frame', '1.9', '19', '3.0M', '1,000+', 'Free', '0', 'Everyone', '', 'February 11, 2018', '1.0.19', '4.0 and up']


['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type', 'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver', 'Android Ver']


['Photo Editor & Candy Camera & Grid & ScrapBook', 'ART_AND_DESIGN', '4.1', '159', '19M', '10,000+', 'Free', '0', 'Everyone', 'Art & Design', 'January 7, 2018', '1.0.0', '4.0.3 and up']

We can see that the app Life Made WI-Fi Touchscreen Photo Frame has a rating of 19 but Google Play only accepts rating up to 5. This confirms that row index 10472 is indeed invalid. Thus, we will remove it from our data set.

In [6]:
print(len(google_play_data))
del google_play_data[10472]
print(len(google_play_data))
10841
10840

Removing Duplicate Entries

Now, we need make to sure every entry is unique. As we explore our data, there are some apps with more than one entry, like the app Instagram:

In [7]:
for app in google_play_data:
    name = app[0]
    if name == 'Instagram':
        print(app, "\n")
['Instagram', 'SOCIAL', '4.5', '66577313', 'Varies with device', '1,000,000,000+', 'Free', '0', 'Teen', 'Social', 'July 31, 2018', 'Varies with device', 'Varies with device'] 

['Instagram', 'SOCIAL', '4.5', '66577446', 'Varies with device', '1,000,000,000+', 'Free', '0', 'Teen', 'Social', 'July 31, 2018', 'Varies with device', 'Varies with device'] 

['Instagram', 'SOCIAL', '4.5', '66577313', 'Varies with device', '1,000,000,000+', 'Free', '0', 'Teen', 'Social', 'July 31, 2018', 'Varies with device', 'Varies with device'] 

['Instagram', 'SOCIAL', '4.5', '66509917', 'Varies with device', '1,000,000,000+', 'Free', '0', 'Teen', 'Social', 'July 31, 2018', 'Varies with device', 'Varies with device'] 

In total, there are 1,181 apps occured more than once.

In [8]:
duplicate_apps = []
unique_apps = []

for app in google_play_data:
    name = app[0]
    if name in unique_apps:
        duplicate_apps.append(name)
    else:
        unique_apps.append(name)
        
print("Number of duplicate apps:", len(duplicate_apps))
print("Example of duplicate apps:", duplicate_apps[:15])
Number of duplicate apps: 1181
Example of duplicate apps: ['Quick PDF Scanner + OCR FREE', 'Box', 'Google My Business', 'ZOOM Cloud Meetings', 'join.me - Simple Meetings', 'Box', 'Zenefits', 'Google Ads', 'Google My Business', 'Slack', 'FreshBooks Classic', 'Insightly CRM', 'QuickBooks Accounting: Invoicing & Expenses', 'HipChat - Chat Built for Teams', 'Xero Accounting Software']

We don't want to count duplicate apps to our analysis, so we need to remove them. If we look at the example of duplicate instagram, the main difference is the 4th column which is the Review column. We can assume that the higher reviews the more up-to-date data. Therefore, we will only keep those data that are up-to-date.

To do that we will:

  • Create a dictionary where each key is unique app name and value is the highest review of that app.
  • Use the new dictionary to create a new data set which only contains unique apps(we select the app with the highest number of reviews)
In [9]:
reviews_max = {}
for app in google_play_data:
    name = app[0]
    n_reviews = float(app[3])
    
    if name in reviews_max and reviews_max[name] < n_reviews:
        reviews_max[name] = n_reviews
    elif name not in reviews_max:
        reviews_max[name] = n_reviews

Since we know that there are 1,181 duplicate apps. Our new dictionary named reviews_max should be equal to the diffence between our data set and 1181.

In [10]:
print("Expected length:", len(google_play_data) - 1181)
print("Actual length:", len(reviews_max))
Expected length: 9659
Actual length: 9659

Now, we will start to create a new data set named android_clean of Google Play that contains only unique apps with ther highest review.

In [11]:
android_clean = []
already_added = []

for app in google_play_data:
    name = app[0]
    n_reviews = float(app[3])
    
    if (n_reviews == reviews_max[name]) and (name not in already_added):
        android_clean.append(app)
        already_added.append(name)

Let's quickly check our new data set and confirm it has 9659 rows.

In [12]:
explore_data(android_clean, 0, 3, True)
['Photo Editor & Candy Camera & Grid & ScrapBook', 'ART_AND_DESIGN', '4.1', '159', '19M', '10,000+', 'Free', '0', 'Everyone', 'Art & Design', 'January 7, 2018', '1.0.0', '4.0.3 and up']


['U Launcher Lite – FREE Live Cool Themes, Hide Apps', 'ART_AND_DESIGN', '4.7', '87510', '8.7M', '5,000,000+', 'Free', '0', 'Everyone', 'Art & Design', 'August 1, 2018', '1.2.4', '4.0.3 and up']


['Sketch - Draw & Paint', 'ART_AND_DESIGN', '4.5', '215644', '25M', '50,000,000+', 'Free', '0', 'Teen', 'Art & Design', 'June 8, 2018', 'Varies with device', '4.2 and up']


Number of rows: 9659
Number of columns: 13

Our new data set android_clean has 9,659 rows, as expected.

Removing Non-english Apps

Since our company only develops mobile apps directly only to English speaking audience. Let's confirm if our data contains any non-English apps. In ASCII (American Standard Code for Information Interchange) system the letter we commonly use in English are all in range of 0 - 127, we can check each app name of our data set if it has a character with greater 127 number encoding.

We created the function below using the built-in ord() function to see the encoding number.

In [13]:
def is_english(string):
    for character in string:
        if ord(character) > 127:
            return False
    return True

print(is_english('Instagram'))
print(is_english('爱奇艺PPS -《欢乐颂2》电视剧热播'))
print(is_english('Docs To Go™ Free Office Suite'))
print(is_english('Instachat 😜'))
True
False
False
False

We see that the last two is most likely targeted for English audience but our function failed to recognize it is an English app. This is because emojis and ™ fall outside of the ASCII range.

If we use our currently function is_english() to remove non-English apps it may cause huge data loss. To minimize, we will only remove if the app name has more than 3 non-ASCII characters.

In [14]:
def is_english(string):
    is_ascii = 0
    for character in string:
        if ord(character) > 127:
            is_ascii += 1
            
    if is_ascii > 3:
        return False
    return True

print(is_english('Instagram'))
print(is_english('Docs To Go™ Free Office Suite'))
print(is_english('Instachat 😜'))
True
True
True

Our function works fine but we know it is not yet really perfect because it may remove some few English apps, but this can be good enough for our analysis.

In [15]:
android_english_apps = []
app_store_english_apps = []

for app in android_clean:
    name = app[0]
    if is_english(name):
        android_english_apps.append(app)
        
for app in apps_store_data:
    name = app[1]
    if is_english(name):
        app_store_english_apps.append(app)
        
explore_data(android_english_apps, 0, 3, True)
print('\n')
explore_data(app_store_english_apps, 0, 3, True)
['Photo Editor & Candy Camera & Grid & ScrapBook', 'ART_AND_DESIGN', '4.1', '159', '19M', '10,000+', 'Free', '0', 'Everyone', 'Art & Design', 'January 7, 2018', '1.0.0', '4.0.3 and up']


['U Launcher Lite – FREE Live Cool Themes, Hide Apps', 'ART_AND_DESIGN', '4.7', '87510', '8.7M', '5,000,000+', 'Free', '0', 'Everyone', 'Art & Design', 'August 1, 2018', '1.2.4', '4.0.3 and up']


['Sketch - Draw & Paint', 'ART_AND_DESIGN', '4.5', '215644', '25M', '50,000,000+', 'Free', '0', 'Teen', 'Art & Design', 'June 8, 2018', 'Varies with device', '4.2 and up']


Number of rows: 9614
Number of columns: 13


['284882215', 'Facebook', '389879808', 'USD', '0.0', '2974676', '212', '3.5', '3.5', '95.0', '4+', 'Social Networking', '37', '1', '29', '1']


['389801252', 'Instagram', '113954816', 'USD', '0.0', '2161558', '1289', '4.5', '4.0', '10.23', '12+', 'Photo & Video', '37', '0', '29', '1']


['529479190', 'Clash of Clans', '116476928', 'USD', '0.0', '2130805', '579', '4.5', '4.5', '9.24.12', '9+', 'Games', '38', '5', '18', '1']


Number of rows: 6183
Number of columns: 16

After removing non-English apps from our data set, Google Play has now 9,614 and the App Store has 6,183.

Removing the Free Apps

We mention earlier that we develop only free apps to download. Both of our data set contains free and non-free apps. So, we'll need to remove non-free apps to our data set.

In [16]:
android_free_apps = []
ios_free_apps = []

for app in android_english_apps:
    price = app[7]
    if price == "0":
        android_free_apps.append(app)
        
for app in app_store_english_apps:
    price = app[4]
    if price == "0.0":
        ios_free_apps.append(app)
        
        
print(len(android_free_apps))
print(len(ios_free_apps))    
8864
3222

So far we cleaned the data with the following steps:

  • Removed innacurate data
  • Removed duplcate data
  • Removed non-English apps
  • isolated free apps

In our final data cleaning we have 8,864 apps for Google Play and 3,222 apps for the App Store.

Data Analyzing

It's time to find what kind of app profile are more likely to succeed on both Google Play and the App Store

Our strategy for an app ideas is:

  1. Build an app for Google Play
  2. If it has a good reviews we will improve it more
  3. If the app is profitable after 6 months, we will build a version for IOS and add it to the App Store

Most Common Apps by Genre

We will build these two functions to analyze frequency tables:

  • A function to generate frequency tables that show percentages.
  • A function that will display the percentages in descending order.
In [17]:
def freq_table(dataset, index):
    frequency_table = {}
    for row in dataset:
        value = row[index]
        if value in frequency_table:
            frequency_table[value] += 1
        else:
            frequency_table[value] = 1
    
    for value in frequency_table:
        frequency_table[value] /= len(dataset)
        frequency_table[value] *= 100
        
    return frequency_table

def display_table(dataset, index):
    table = freq_table(dataset, index)
    table_display = []
    for key in table:
        key_val_as_tuple = (table[key], key)
        table_display.append(key_val_as_tuple)

    table_sorted = sorted(table_display, reverse = True)
    for entry in table_sorted:
        print(entry[1], ':', entry[0])

We can now use our function named display_table() to analyze our data set. Let's start with the App Store data set for the prime_genre column.

In [18]:
display_table(ios_free_apps, -5)
Games : 58.16263190564867
Entertainment : 7.883302296710118
Photo & Video : 4.9658597144630665
Education : 3.662321539416512
Social Networking : 3.2898820608317814
Shopping : 2.60707635009311
Utilities : 2.5139664804469275
Sports : 2.1415270018621975
Music : 2.0484171322160147
Health & Fitness : 2.0173805090006205
Productivity : 1.7380509000620732
Lifestyle : 1.5828677839851024
News : 1.3345747982619491
Travel : 1.2414649286157666
Finance : 1.1173184357541899
Weather : 0.8690254500310366
Food & Drink : 0.8069522036002483
Reference : 0.5586592178770949
Business : 0.5276225946617008
Book : 0.4345127250155183
Navigation : 0.186219739292365
Medical : 0.186219739292365
Catalogs : 0.12414649286157665

We can see from the result that more than half of the App Store is Games(58.16%). While Entertainment with almost 8% followed by Photo & Video with almost 5%.

The general impression is that the App Store(at least the part container free English Apps) dominated by apps for fun, such as games, entertainment, photo and video, etc. While practical purposes apps like utilities, shopping, sports, health & fitness, etc are more rare. However more apps in particular part doesn't mean is also has numerous users - demand might not be the same as the offer.

Let's continue by exploring Google Play data set Category and Genres column.

In [19]:
display_table(android_free_apps, 1) # category
FAMILY : 18.907942238267147
GAME : 9.724729241877256
TOOLS : 8.461191335740072
BUSINESS : 4.591606498194946
LIFESTYLE : 3.9034296028880866
PRODUCTIVITY : 3.892148014440433
FINANCE : 3.7003610108303246
MEDICAL : 3.531137184115524
SPORTS : 3.395758122743682
PERSONALIZATION : 3.3167870036101084
COMMUNICATION : 3.2378158844765346
HEALTH_AND_FITNESS : 3.0798736462093865
PHOTOGRAPHY : 2.944494584837545
NEWS_AND_MAGAZINES : 2.7978339350180503
SOCIAL : 2.6624548736462095
TRAVEL_AND_LOCAL : 2.33528880866426
SHOPPING : 2.2450361010830324
BOOKS_AND_REFERENCE : 2.1435018050541514
DATING : 1.861462093862816
VIDEO_PLAYERS : 1.7937725631768955
MAPS_AND_NAVIGATION : 1.3989169675090252
FOOD_AND_DRINK : 1.2409747292418771
EDUCATION : 1.1620036101083033
ENTERTAINMENT : 0.9589350180505415
LIBRARIES_AND_DEMO : 0.9363718411552346
AUTO_AND_VEHICLES : 0.9250902527075812
HOUSE_AND_HOME : 0.8235559566787004
WEATHER : 0.8009927797833934
EVENTS : 0.7107400722021661
PARENTING : 0.6543321299638989
ART_AND_DESIGN : 0.6430505415162455
COMICS : 0.6204873646209386
BEAUTY : 0.5979241877256317

We see Google Play has different result, being family in the top with almost 19% followed by game with 9.7%. Seems like Google Play has much more with practical apps like tools, business, lifestyle, productivity, etc. Howerver, if check in Google Play family category is consist of games for kids.

img

We can have a better represention of Google Play if we check the Genres column.

In [20]:
display_table(android_free_apps, 9) # genre
Tools : 8.449909747292418
Entertainment : 6.069494584837545
Education : 5.347472924187725
Business : 4.591606498194946
Productivity : 3.892148014440433
Lifestyle : 3.892148014440433
Finance : 3.7003610108303246
Medical : 3.531137184115524
Sports : 3.463447653429603
Personalization : 3.3167870036101084
Communication : 3.2378158844765346
Action : 3.1024368231046933
Health & Fitness : 3.0798736462093865
Photography : 2.944494584837545
News & Magazines : 2.7978339350180503
Social : 2.6624548736462095
Travel & Local : 2.3240072202166067
Shopping : 2.2450361010830324
Books & Reference : 2.1435018050541514
Simulation : 2.0419675090252705
Dating : 1.861462093862816
Arcade : 1.8501805054151623
Video Players & Editors : 1.7712093862815883
Casual : 1.7599277978339352
Maps & Navigation : 1.3989169675090252
Food & Drink : 1.2409747292418771
Puzzle : 1.128158844765343
Racing : 0.9927797833935018
Role Playing : 0.9363718411552346
Libraries & Demo : 0.9363718411552346
Auto & Vehicles : 0.9250902527075812
Strategy : 0.9138086642599278
House & Home : 0.8235559566787004
Weather : 0.8009927797833934
Events : 0.7107400722021661
Adventure : 0.6768953068592057
Comics : 0.6092057761732852
Beauty : 0.5979241877256317
Art & Design : 0.5979241877256317
Parenting : 0.4963898916967509
Card : 0.45126353790613716
Casino : 0.42870036101083037
Trivia : 0.41741877256317694
Educational;Education : 0.39485559566787
Board : 0.3835740072202166
Educational : 0.3722924187725632
Education;Education : 0.33844765342960287
Word : 0.2594765342960289
Casual;Pretend Play : 0.236913357400722
Music : 0.2030685920577617
Racing;Action & Adventure : 0.16922382671480143
Puzzle;Brain Games : 0.16922382671480143
Entertainment;Music & Video : 0.16922382671480143
Casual;Brain Games : 0.13537906137184114
Casual;Action & Adventure : 0.13537906137184114
Arcade;Action & Adventure : 0.12409747292418773
Action;Action & Adventure : 0.10153429602888085
Educational;Pretend Play : 0.09025270758122744
Simulation;Action & Adventure : 0.078971119133574
Parenting;Education : 0.078971119133574
Entertainment;Brain Games : 0.078971119133574
Board;Brain Games : 0.078971119133574
Parenting;Music & Video : 0.06768953068592057
Educational;Brain Games : 0.06768953068592057
Casual;Creativity : 0.06768953068592057
Art & Design;Creativity : 0.06768953068592057
Education;Pretend Play : 0.056407942238267145
Role Playing;Pretend Play : 0.04512635379061372
Education;Creativity : 0.04512635379061372
Role Playing;Action & Adventure : 0.033844765342960284
Puzzle;Action & Adventure : 0.033844765342960284
Entertainment;Creativity : 0.033844765342960284
Entertainment;Action & Adventure : 0.033844765342960284
Educational;Creativity : 0.033844765342960284
Educational;Action & Adventure : 0.033844765342960284
Education;Music & Video : 0.033844765342960284
Education;Brain Games : 0.033844765342960284
Education;Action & Adventure : 0.033844765342960284
Adventure;Action & Adventure : 0.033844765342960284
Video Players & Editors;Music & Video : 0.02256317689530686
Sports;Action & Adventure : 0.02256317689530686
Simulation;Pretend Play : 0.02256317689530686
Puzzle;Creativity : 0.02256317689530686
Music;Music & Video : 0.02256317689530686
Entertainment;Pretend Play : 0.02256317689530686
Casual;Education : 0.02256317689530686
Board;Action & Adventure : 0.02256317689530686
Video Players & Editors;Creativity : 0.01128158844765343
Trivia;Education : 0.01128158844765343
Travel & Local;Action & Adventure : 0.01128158844765343
Tools;Education : 0.01128158844765343
Strategy;Education : 0.01128158844765343
Strategy;Creativity : 0.01128158844765343
Strategy;Action & Adventure : 0.01128158844765343
Simulation;Education : 0.01128158844765343
Role Playing;Brain Games : 0.01128158844765343
Racing;Pretend Play : 0.01128158844765343
Puzzle;Education : 0.01128158844765343
Parenting;Brain Games : 0.01128158844765343
Music & Audio;Music & Video : 0.01128158844765343
Lifestyle;Pretend Play : 0.01128158844765343
Lifestyle;Education : 0.01128158844765343
Health & Fitness;Education : 0.01128158844765343
Health & Fitness;Action & Adventure : 0.01128158844765343
Entertainment;Education : 0.01128158844765343
Communication;Creativity : 0.01128158844765343
Comics;Creativity : 0.01128158844765343
Casual;Music & Video : 0.01128158844765343
Card;Action & Adventure : 0.01128158844765343
Books & Reference;Education : 0.01128158844765343
Art & Design;Pretend Play : 0.01128158844765343
Art & Design;Action & Adventure : 0.01128158844765343
Arcade;Pretend Play : 0.01128158844765343
Adventure;Education : 0.01128158844765343

The difference between Genres and Category is unclear but we can notice is that the Genres are much more granular. For this analysis we will only work with Category column and move on.

This first analysis we can conclude that App Store is dominated by apps designed for fun, while Google Play has much more balance on for-fun and practical apps.

To find out what genres has more user in the app store is to calculate the average of installs for each genre. In Google Play we can use the Installs column but this column is missing for the App Store. As a workaround we can use the number of ratings which is the rating_count_tot.

Below, we calculate the average users of each genre on the App Store.

In [21]:
genres_ios = freq_table(ios_free_apps, -5)

frequency_rating_genre = {}
for genre in genres_ios:
    total = 0
    len_genre = 0
    for row in ios_free_apps:
        genre_app = row[-5]
        if genre_app == genre:
            n_ratings = float(row[5])
            total += n_ratings
            len_genre += 1
    avg_n_ratings = total / len_genre
    frequency_rating_genre[genre] = avg_n_ratings
    
# To sort out the values in frequency_rating_genre by descending order
frequency_rating_genre = {k: v for k, v in sorted(frequency_rating_genre.items(), key=lambda item: item[1],  reverse = True)}

for rating in frequency_rating_genre:
    print(rating,":",frequency_rating_genre[rating])
Navigation : 86090.33333333333
Reference : 74942.11111111111
Social Networking : 71548.34905660378
Music : 57326.530303030304
Weather : 52279.892857142855
Book : 39758.5
Food & Drink : 33333.92307692308
Finance : 31467.944444444445
Photo & Video : 28441.54375
Travel : 28243.8
Shopping : 26919.690476190477
Health & Fitness : 23298.015384615384
Sports : 23008.898550724636
Games : 22788.6696905016
News : 21248.023255813954
Productivity : 21028.410714285714
Utilities : 18684.456790123455
Lifestyle : 16485.764705882353
Entertainment : 14029.830708661417
Business : 7491.117647058823
Education : 7003.983050847458
Catalogs : 4004.0
Medical : 612.0

We see that navigation has the highest number of users on average. Let's check if this result is fairly distributed.

In [22]:
for app in ios_free_apps:
    if app[-5] == "Navigation":
        print(app[1], ":", app[5])
Waze - GPS Navigation, Maps & Real-time Traffic : 345046
Google Maps - Navigation & Transit : 154911
Geocaching® : 12811
CoPilot GPS – Car Navigation & Offline Maps : 3582
ImmobilienScout24: Real Estate Search in Germany : 187
Railway Route Search : 5
In [23]:
for app in ios_free_apps:
    if app[-5] == "Reference":
        print(app[1], ":", app[5])
Bible : 985920
Dictionary.com Dictionary & Thesaurus : 200047
Dictionary.com Dictionary & Thesaurus for iPad : 54175
Google Translate : 26786
Muslim Pro: Ramadan 2017 Prayer Times, Azan, Quran : 18418
New Furniture Mods - Pocket Wiki & Game Tools for Minecraft PC Edition : 17588
Merriam-Webster Dictionary : 16849
Night Sky : 12122
City Maps for Minecraft PE - The Best Maps for Minecraft Pocket Edition (MCPE) : 8535
LUCKY BLOCK MOD ™ for Minecraft PC Edition - The Best Pocket Wiki & Mods Installer Tools : 4693
GUNS MODS for Minecraft PC Edition - Mods Tools : 1497
Guides for Pokémon GO - Pokemon GO News and Cheats : 826
WWDC : 762
Horror Maps for Minecraft PE - Download The Scariest Maps for Minecraft Pocket Edition (MCPE) Free : 718
VPN Express : 14
Real Bike Traffic Rider Virtual Reality Glasses : 8
教えて!goo : 0
Jishokun-Japanese English Dictionary & Translator : 0

Both Navigation and Reference are heavily influnced by few giants like Waze, Google Maps, Bible, etc. Also applies with music with Pandora, Spotify and Shazam heavily influcend the average number.

Now, let's check the most install apps for Google Play Store.

In [24]:
display_table(android_free_apps, 5)
1,000,000+ : 15.726534296028879
100,000+ : 11.552346570397113
10,000,000+ : 10.548285198555957
10,000+ : 10.198555956678701
1,000+ : 8.393501805054152
100+ : 6.915613718411552
5,000,000+ : 6.825361010830325
500,000+ : 5.561823104693141
50,000+ : 4.7721119133574
5,000+ : 4.512635379061372
10+ : 3.5424187725631766
500+ : 3.2490974729241873
50,000,000+ : 2.3014440433213
100,000,000+ : 2.1322202166064983
50+ : 1.917870036101083
5+ : 0.78971119133574
1+ : 0.5076714801444043
500,000,000+ : 0.2707581227436823
1,000,000,000+ : 0.22563176895306858
0+ : 0.04512635379061372
0 : 0.01128158844765343

One problem with this data is that is not precise. For example we have 100,000+ installs, 500,000+ install. However, in this analysis we don't need very precise data as we are only looking for which apps has more installs for genre.

Therefore, we will leave the number of installs as it is and remove plus character of each end. Before we start we need to convert our each install to float, so we need to remove commas and plus characters. We will do this on a loop and compute the average of installs for each genre.

In [25]:
categories_android = freq_table(android_free_apps, 1)

frequency_category_install = {}
for category in categories_android:
    total = 0
    len_category = 0
    for app in android_free_apps:
        category_app = app[1]
        if category_app == category:
            n_install = app[5]
            n_install = n_install.replace('+', '')
            n_install = n_install.replace(',', '')
            total += float(n_install)
            len_category += 1
    avg_n_installs = total / len_category
    frequency_category_install[category] = avg_n_installs
    
# To sort out the values in frequency_category_install by descending order  
frequency_category_install = {k: v for k, v in sorted(frequency_category_install.items(), key=lambda item: item[1],  reverse = True)}
    
for install in frequency_category_install:
    print(install, ":", frequency_category_install[install])
    
COMMUNICATION : 38456119.167247385
VIDEO_PLAYERS : 24727872.452830188
SOCIAL : 23253652.127118643
PHOTOGRAPHY : 17840110.40229885
PRODUCTIVITY : 16787331.344927534
GAME : 15588015.603248259
TRAVEL_AND_LOCAL : 13984077.710144928
ENTERTAINMENT : 11640705.88235294
TOOLS : 10801391.298666667
NEWS_AND_MAGAZINES : 9549178.467741935
BOOKS_AND_REFERENCE : 8767811.894736841
SHOPPING : 7036877.311557789
PERSONALIZATION : 5201482.6122448975
WEATHER : 5074486.197183099
HEALTH_AND_FITNESS : 4188821.9853479853
MAPS_AND_NAVIGATION : 4056941.7741935486
FAMILY : 3695641.8198090694
SPORTS : 3638640.1428571427
ART_AND_DESIGN : 1986335.0877192982
FOOD_AND_DRINK : 1924897.7363636363
EDUCATION : 1833495.145631068
BUSINESS : 1712290.1474201474
LIFESTYLE : 1437816.2687861272
FINANCE : 1387692.475609756
HOUSE_AND_HOME : 1331540.5616438356
DATING : 854028.8303030303
COMICS : 817657.2727272727
AUTO_AND_VEHICLES : 647317.8170731707
LIBRARIES_AND_DEMO : 638503.734939759
PARENTING : 542603.6206896552
BEAUTY : 513151.88679245283
EVENTS : 253542.22222222222
MEDICAL : 120550.61980830671

Let's check a number of apps heavily influenced our result.

In [26]:
for app in android_free_apps:
    if app[1] == 'COMMUNICATION' and (app[5] == '1,000,000,000+' or app[5] == '500,000,000+' or app[5] == '100,000,000+'):
        print(app[0], ":", app[5])
WhatsApp Messenger : 1,000,000,000+
imo beta free calls and text : 100,000,000+
Android Messages : 100,000,000+
Google Duo - High Quality Video Calls : 500,000,000+
Messenger – Text and Video Chat for Free : 1,000,000,000+
imo free video calls and chat : 500,000,000+
Skype - free IM & video calls : 1,000,000,000+
Who : 100,000,000+
GO SMS Pro - Messenger, Free Themes, Emoji : 100,000,000+
LINE: Free Calls & Messages : 500,000,000+
Google Chrome: Fast & Secure : 1,000,000,000+
Firefox Browser fast & private : 100,000,000+
UC Browser - Fast Download Private & Secure : 500,000,000+
Gmail : 1,000,000,000+
Hangouts : 1,000,000,000+
Messenger Lite: Free Calls & Messages : 100,000,000+
Kik : 100,000,000+
KakaoTalk: Free Calls & Text : 100,000,000+
Opera Mini - fast web browser : 100,000,000+
Opera Browser: Fast and Secure : 100,000,000+
Telegram : 100,000,000+
Truecaller: Caller ID, SMS spam blocking & Dialer : 100,000,000+
UC Browser Mini -Tiny Fast Private & Secure : 100,000,000+
Viber Messenger : 500,000,000+
WeChat : 100,000,000+
Yahoo Mail – Stay Organized : 100,000,000+
BBM - Free Calls & Messages : 100,000,000+
In [27]:
for app in android_free_apps:
    if app[1] == 'VIDEO_PLAYERS' and (app[5] == '1,000,000,000+' or app[5] == '500,000,000+' or app[5] == '100,000,000+'):
        print(app[0], ":", app[5])
YouTube : 1,000,000,000+
Motorola Gallery : 100,000,000+
VLC for Android : 100,000,000+
Google Play Movies & TV : 1,000,000,000+
MX Player : 500,000,000+
Dubsmash : 100,000,000+
VivaVideo - Video Editor & Photo Movie : 100,000,000+
VideoShow-Video Editor, Video Maker, Beauty Camera : 100,000,000+
Motorola FM Radio : 100,000,000+

We can say that that communication have a fine share with giants like Google Chrome, Messenger, WhatsApp and Skype while the rest being in 100,000+ installs. While Video players is heavily influenced by both YouTube and Google Play Movies & TV which has 1,000,000+ installs.

Conclusion

In this project, we analyzed the data about Google Play and the App Store with an aim of finding a profitable app for both markets.

It's very clear that the App Store and Google Play are dominated by Games. We conclude that taking a game is profitable. However, there are really many kind of games. After taking this data analyzing we may want to look for another data set this time is about games in both Google Play and the App store before deriving to a final conclusion what kind of game we will make.