Google Play ストアのアプリとレビュー¶

現在モバイルアプリはどこにでもあります。作成は簡単で、収益性が高く、これらの要因により、ますます多くのアプリが開発されています。
Google Play のさまざまなカテゴリにわたる 1 万以上のアプリを比較することにより、Android アプリ市場の包括的な分析を行います。
データから洞察を見つけて、成長と維持を促進する戦略を考案します。


1. データの読み込み¶

2 つのファイルで構成されるデータを見てみましょう。

  • apps.csv: Google Play 上のアプリケーションの詳細がすべて含まれています。特定のアプリを説明する 13 の機能があります。
  • user_reviews.csv: 各アプリについて 100 件のレビューが含まれます。最も役立つものから順にセクションを使用すると、星評価で簡単にフィルタリングできます/)。各レビューのテキストは前処理され、感情 (肯定的、否定的、または中立)、感情の極性、感情の主観性という 3 つの新しい機能によって属性が付けられます。

ライブラリをインポートします。

from zipfile import ZipFile
from io import BytesIO
import pandas as pd
import numpy as np
import plotly
plotly.offline.init_notebook_mode(connected=True)
import plotly.graph_objs as go

zipファイルからファイル名を取得し、pandasデータフレームとして読み込みます。

zf = ZipFile('datasets.zip')
zf.namelist()
['datasets/',
 'datasets/apps.csv',
 'datasets/Untitled Folder/',
 'datasets/user_reviews.csv']
apps = pd.read_csv(BytesIO(zf.read(zf.namelist()[1])))
apps = apps.drop_duplicates()
print('データセット内のアプリの総数 = ', apps.shape[0])

apps.sample(5)
データセット内のアプリの総数 =  9659
Unnamed: 0 App Category Rating Reviews Size Installs Type Price Content Rating Genres Last Updated Current Ver Android Ver
8714 9868 myLPG.eu TRAVEL_AND_LOCAL 4.2 556 4.4 50,000+ Free 0 Everyone Travel & Local July 25, 2018 1.95 4.0 and up
573 700 TED EDUCATION 4.6 181893 18.0 10,000,000+ Free 0 Everyone 10+ Education July 27, 2018 3.2.5 4.1 and up
3824 4754 X Browser COMMUNICATION 4.0 142 2.5 50,000+ Free 0 Everyone Communication December 31, 2017 1.1.1 4.0 and up
1430 1769 Woody Puzzle GAME 4.7 21262 29.0 1,000,000+ Free 0 Everyone Puzzle August 3, 2018 1.0.9 4.4 and up
2964 3723 Wireless news NEWS_AND_MAGAZINES 3.5 6066 56.0 1,000,000+ Free 0 Everyone News & Magazines April 16, 2018 2.1.4 4.4 and up

2. データのクリーニング¶

データクリーニングは、データ サイエンス プロジェクトの最も重要なプロセスの1つです。非常に面倒なプロセスですが、データ価値が損なわれていけません。

(上記のタスクからの) データセット行のランダム サンプルを確認すると、数値の表現方法により、Installs や Price などの列の一部のエントリにいくつかの特殊文字 (+ , $) が含まれていることがわかります。
これにより、列を純粋な数値にすることができなくなり、その後の数学的計算で列を使用することが困難になります。
理想的には、数値が計算できるように、これらの列には [0-9] の数字のみが含まれるようにする必要があります。

クリーニングの完了後に、データフレームの概要を出力して確認することも重要です。
これを実行するには info() メソッドを使用します。

  1. 削除する文字リストを定義
  2. クリーンアップする列名リストを定義
  3. 列名リストをループ
  4. その中で更に文字リストをループ
  5. 文字を空の文字列""に置き換える
chars_to_remove = ['+', ',' ,'$']
cols_to_clean = ['Installs', 'Price']

for col in cols_to_clean:
    for char in chars_to_remove:
        apps[col] = apps[col].apply(lambda x: x.replace(char, ''))

apps.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 9659 entries, 0 to 9658
Data columns (total 14 columns):
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   Unnamed: 0      9659 non-null   int64  
 1   App             9659 non-null   object 
 2   Category        9659 non-null   object 
 3   Rating          8196 non-null   float64
 4   Reviews         9659 non-null   int64  
 5   Size            8432 non-null   float64
 6   Installs        9659 non-null   object 
 7   Type            9659 non-null   object 
 8   Price           9659 non-null   object 
 9   Content Rating  9659 non-null   object 
 10  Genres          9659 non-null   object 
 11  Last Updated    9659 non-null   object 
 12  Current Ver     9651 non-null   object 
 13  Android Ver     9657 non-null   object 
dtypes: float64(2), int64(2), object(10)
memory usage: 1.1+ MB

3. データタイプの修正¶

上述のタスクから、Installs と Price がobjectデータ型 (int や float ではなく) として分類されていることがわかりました。
これは、これら 2 つの列にはもともと数字と特殊文字の入力タイプが混在していたためです。

Pandas データ型の詳細については、こちら を参照。

今後最も頻繁に使用する 4 つの機能は、Installs、 Size、 Rating、 Priceです。
SizeとRating はどちらもfloat(数値データ型)ですが、InstallsとPriceを数値にするために、更に作業する必要があります。

  1. Installを float データ型に変換
  2. Priceをfloatデータ型に変換
import numpy as np

apps['Installs'] = apps['Installs'].astype(float)

apps['Price'] = apps['Price'].astype(float)

apps.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 9659 entries, 0 to 9658
Data columns (total 14 columns):
 #   Column          Non-Null Count  Dtype  
---  ------          --------------  -----  
 0   Unnamed: 0      9659 non-null   int64  
 1   App             9659 non-null   object 
 2   Category        9659 non-null   object 
 3   Rating          8196 non-null   float64
 4   Reviews         9659 non-null   int64  
 5   Size            8432 non-null   float64
 6   Installs        9659 non-null   float64
 7   Type            9659 non-null   object 
 8   Price           9659 non-null   float64
 9   Content Rating  9659 non-null   object 
 10  Genres          9659 non-null   object 
 11  Last Updated    9659 non-null   object 
 12  Current Ver     9651 non-null   object 
 13  Android Ver     9657 non-null   object 
dtypes: float64(4), int64(2), object(8)
memory usage: 1.1+ MB

4. アプリのカテゴリを調べる¶

世界 190 か国に 10 億人を超えるアクティブ ユーザーがいる Google Play は、世界中の視聴者を構築するための重要な配信プラットフォームであり続けています。
企業がアプリをユーザーに提供するには、アプリを Google Play でより迅速かつ簡単に見つけられるようにすることが重要です。
全体的な検索エクスペリエンスを向上させるために、Google はアプリをカテゴリにグループ化する概念を導入しました。

これにより、次のような疑問が生じます。

  • 市場で(アクティブな)アプリのシェアが最も高いのカテゴリーは何か
  • 市場を支配している特定のカテゴリーはあるのか
  • アプリの数が最も少ないカテゴリーはどれか

カテゴリーごとのアプリ数をグラフで表示します。

num_categories = len(apps['Category'].unique())
print('カテゴリー数 = ', num_categories)

num_apps_in_category = apps['Category'].value_counts()


sorted_num_apps_in_category = num_apps_in_category.sort_values(ascending=False)

data = [go.Bar(
                x = num_apps_in_category.index,
                y = num_apps_in_category.values,
                )]

plotly.offline.iplot(data)
カテゴリー数 =  33

データセットには 33 のカテゴリが存在することがわかります。
FAMILY が最も多く、続いて GAME 、 TOOLS が市場で普及しています。
BUSINESS 、MEDICAL アプリも上位にあります。

5. アプリ評価の分布¶

アプリの各カテゴリの市場シェアを確認した後、これらすべてのアプリが平均してどのようにパフォーマンスを発揮するかを見てみます。
アプリ評価 (1 から 5 のスケール) は、アプリの見つけやすさ、コンバージョン、そして会社全体のブランド イメージに影響を与えます。
評価はアプリの重要なパフォーマンス指標です。

アプリの評価をグラフに表示します。

avg_app_rating = apps['Rating'].mean()
print('アプリの平均評価 = ', avg_app_rating)


data = [go.Histogram(
                    x = apps['Rating']
                    )]


layout = {'shapes': [{
                      'type' :'line',
                      'x0': avg_app_rating,
                      'y0': 0,
                      'x1': avg_app_rating,
                      'y1': 1000,
                      'line': { 'dash': 'dashdot'}
                      }]
                          }

plotly.offline.iplot({'data': data, 'layout': layout})
アプリの平均評価 =  4.173243045387994

データから、すべてのアプリカテゴリにわたる評価の平均量は 4.17 であることがわかりました。

ヒストグラムでは一部のレートに偏りが見られます。
これは、低評価のアプリの少数の例外を除いて、大部分のアプリが高評価されていることを示しています。

6. アプリのサイズと価格¶

次に、アプリのサイズとアプリの価格を調べてみます。
サイズに関しては、アプリのデータサイズが大きすぎると、ユーザーがダウンロードするのが難しくなったり、ダウンロードが高価になったりする可能性があります。   ダウンロード時間が長いと、モバイル アプリを体験する前にユーザーが離れてしまう可能性があります。
そして各ユーザーのデバイスの容量には限りがあります。
価格は、アプリが無料か安価であることを期待するユーザーもいます。
発展途上国がターゲット市場の一部である場合、これらの問題はさらに複雑になります。
特にインターネットの速度、収益力、為替レートによるものです。

アプリのサイズと価格を設定する戦略を効果的に考案するために以下を調査します。

  • アプリのサイズは評価に影響するのか
  • ユーザーはシステム負荷の高いアプリを本当に気にしているのか、それとも軽量のアプリを好むのか
  • アプリの価格は評価に影響するのか
  • ユーザーは常に有料アプリよりも無料アプリを好むのか
  1. Rating とSize の両方のデータが存在する行を選択
  2. 少なくとも 250 個のアプリを含むカテゴリのサブセットとする
  3. Size とRating を出力
  4. Type が Paid (有料)のアプリを選択
  5. Priceと Rating を出力
%matplotlib inline
import seaborn as sns
sns.set_style("darkgrid")
import warnings
warnings.filterwarnings("ignore")

apps_with_size_and_rating_present = apps[(~apps['Rating'].isnull()) & (~apps['Size'].isnull())]

large_categories = apps_with_size_and_rating_present.groupby("Category").filter(lambda x: len(x) >= 250)

plt1 = sns.jointplot(x = large_categories["Size"],
                     y = large_categories["Rating"],
                     height=8)

paid_apps = apps_with_size_and_rating_present[apps_with_size_and_rating_present['Type']=='Paid']

plt2 = sns.jointplot(x = paid_apps["Price"],
                     y = paid_apps["Rating"],
                     height=8)

最も評価の高いアプリ (評価 4 以上) の大半は 2 MB から 20 MB の範囲であることがわかります。
また、大多数のアプリの価格は 50 ドル未満であることもわかります。

ここで 50 ドル以下のアプリに限定したデータで価格の詳細を出力してみます。

sns.relplot(data = paid_apps[paid_apps.Price <= 50],
            y = "Price",
            x = "Rating",
            hue = 'Size',
            alpha = .5,
            height = 6,
            aspect = 1.6, 
            size = 'Size',
            sizes=(100, 500),
            palette ="muted",
            legend = False
        )
<seaborn.axisgrid.FacetGrid at 0x7f9d5ee05e80>

ほとんどが 5 ドル以下であることがわかりました。

7. アプリカテゴリとアプリ価格の関係¶

企業や開発者はどうやって支出計画を立てるべきなのでしょうか。
企業は利益を最大化するためにどのような収益化戦略を使用できるにでしょうか。
アプリのコストは主に、機能、複雑さ、プラットフォームによって決まります。

モバイル アプリに適切な価格設定戦略を選択する際には、考慮すべき要素が数多くあります。顧客がアプリに対して支払いを行う意思があるかどうかを考慮することが重要です。
価格を間違えると、ダウンロードが行われる前に契約が破棄される可能性があります。
潜在的な顧客は、衝撃的な費用であると感じて離れてしまう可能性があります。
あるいは、あまりにも多くの広告を受信したり、単にお金の価値がなかったため、ダウンロードしたアプリを削除したりする可能性があります。

  1. 人気のあるアプリのカテゴリをいくつか選択します
  2. 価格とカテゴリをグラフ化して価格傾向を調べます
  3. 価格が200ドルを超えるアプリを見てみます
import matplotlib.pyplot as plt
import japanize_matplotlib
sns.set(font="IPAexGothic")
fig, ax = plt.subplots()
fig.set_size_inches(14, 6)

popular_app_cats = apps[apps.Category.isin(['GAME', 'FAMILY', 'PHOTOGRAPHY',
                                            'MEDICAL', 'TOOLS', 'FINANCE',
                                            'LIFESTYLE','BUSINESS'])]

ax = sns.stripplot(data = popular_app_cats,
                   x = popular_app_cats['Price'],
                   y = popular_app_cats["Category"],
                   jitter=True,
                   linewidth=1,
                   alpha = .5,
                   hue = "Category",
                   legend=False
                  )

ax.set_title('カテゴリ別のアプリ価格の傾向', size=20)
plt.xlabel('Price', labelpad=15, size=14)
plt.ylabel("カ\nテ\nゴ\nリ", labelpad=18, size=14, rotation=0, va='center')
plt.show()
apps_above_200 = popular_app_cats[popular_app_cats['Price'] > 200]
apps_above_200[['Category', 'App', 'Price']]
Category App Price
3327 FAMILY most expensive app (H) 399.99
3465 LIFESTYLE 💎 I'm rich 399.99
3469 LIFESTYLE I'm Rich - Trump Edition 400.00
4396 LIFESTYLE I am rich 399.99
4398 FAMILY I am Rich Plus 399.99
4399 LIFESTYLE I am rich VIP 299.99
4400 FINANCE I Am Rich Premium 399.99
4401 LIFESTYLE I am extremely Rich 379.99
4402 FINANCE I am Rich! 399.99
4403 FINANCE I am rich(premium) 399.99
4406 FAMILY I Am Rich Pro 399.99
4408 FINANCE I am rich (Most expensive app) 399.99
4410 FAMILY I Am Rich 389.99
4413 FINANCE I am Rich 399.99
4417 FINANCE I AM RICH PRO PLUS 399.99
8763 FINANCE Eu Sou Rico 394.99
8780 LIFESTYLE I'm Rich/Eu sou Rico/أنا غني/我很有錢 399.99

カテゴリーが異なれば、求められる価格帯も異なります。
電卓アプリなど、シンプルで毎日使用する一部のアプリは、おそらく無料にしておくべきでしょう。
しかし、糖尿病患者を診断する高度に専門化された医療アプリに課金するのは理にかなっています。
以下では、MEDICAL および FAMILY アプリが最も高価であることがわかります。
すべてのゲーム アプリは 20 ドル以下の手頃な価格です。

8. ジャンクアプリを除外する¶

本当に高価なアプリの多くは「ジャンク」アプリのようです。つまり、実際には目的を持たないアプリです。
アプリ開発者によっては、冗談のため、またはアプリ開発スキルをテストするためだけに、I Am Rich Premium または most expensive app (H) という名前のアプリを作成する場合があります。
一部の開発者は悪意を持ってこれを実行し、ユーザーがストアでアプリの購入を誤ってクリックすることを期待してお金を稼ごうとします。

これらの迷惑アプリをフィルタリングして除外し、視覚化をやり直してみます。

  1. 100ドル未満のアプリを選択します
  2. 本物のアプリ (apps_under_100) で価格とカテゴリを調べます
# Select apps priced below $100
apps_under_100 = popular_app_cats[popular_app_cats['Price'] < 100]

fig, ax = plt.subplots()
fig.set_size_inches(14, 6)

# Examine price vs category with the authentic apps (apps_under_100)
ax = sns.stripplot(x = "Price",
                   y = 'Category',
                   data = apps_under_100,
                   jitter = True,
                   linewidth = 1,
                   alpha = .5,
                   hue = "Category",
                   legend=False
                  )

ax.set_title('ジャンクアプリ排除後のカテゴリ別のアプリ価格傾向', size=20)
plt.xlabel('Price', labelpad=15, size=14)
plt.ylabel("カ\nテ\nゴ\nリ", labelpad=18, size=14, rotation=0, va='center')
plt.show()

9. 有料アプリと無料アプリの人気¶

現在、Play ストアのアプリには、無料、フリーミアム、有料、ペイミアム、サブスクリプションの 5 種類の価格設定戦略があります。
無料アプリと有料アプリのみに焦点を当てます。
無料アプリには次のような特徴があります。

  • 無料ダウンロード
  • 主な収入源は広告であることが多い
  • 多くの場合、他の製品を所有する企業によって作成され、アプリはそれらの製品の拡張として機能
  • 顧客維持、コミュニケーション、顧客サービスのツールとして機能

有料アプリには次のような特徴があります。

  • ユーザーは、アプリをダウンロードして使用するために一度支払いを求められる
  • ユーザーは購入する前にアプリの感触を実際に知ることができない

有料アプリは無料アプリと同じくらいインストールされているのか視覚化します。

trace0 = go.Box(
                y = apps[apps['Type'] == "Paid"]['Installs'],
                name = 'Paid'
                )

trace1 = go.Box(
                y = apps[apps['Type'] == "Free"]['Installs'],
                name = 'Free'
                )

layout = go.Layout(
                title = "有料アプリと無料アプリのダウンロード数",
                yaxis = dict(title = "ダウンロード数のログ",
                            type = 'log',
                            autorange = True)
                )

data = [trace0, trace1]
plotly.offline.iplot({'data': data, 'layout': layout})

有料アプリのインストール数は無料アプリよりも相対的に低いことがわかりましたが、さほど顕著ではありませんでした。

10. ユーザーレビューの感情分析¶

ユーザー レビュー データをマイニングして、製品、ブランド、サービスについて人々がどのように感じているかを判断するには、センチメント分析を使用します。
アプリのユーザー レビューを分析して、そのアプリに対する雰囲気が肯定的か否定的か、中立的かを特定できます。
たとえば、アプリのレビューの肯定的な言葉には、「素晴らしい」、「フレンドリー」、「良い」、「素晴らしい」、「愛」などの言葉が含まれる場合があります。
否定的な言葉としては、「マルウェア」、「嫌い」、「問題」、「返金」、「無能」などの言葉が考えられます。

  1. user_reviews.csvをロードする
  2. Sentiment を使用するために2 つのデータフレームを結合
  3. NA 値をセンチメント列とレビュー列から削除
  4. 有料アプリと無料アプリに対するユーザー レビューの感情の極性を表示
merged_df[merged_df['Type'] == "Paid"]['Sentiment_Polarity']
30241   -0.209091
30242    0.552000
30243    0.215238
30244   -0.094805
30245    0.300000
           ...   
52822    0.600000
52823    0.811111
52824    0.250000
52825    0.016667
52826    0.220833
Name: Sentiment_Polarity, Length: 416, dtype: float64
trace0 = go.Box(y = merged_df[merged_df['Type'] == "Paid"]['Sentiment_Polarity'],
                name = 'Paid')

trace1 = go.Box(y = merged_df[merged_df['Type'] == "Free"]['Sentiment_Polarity'],
                name = 'Free')

layout = go.Layout(
                title = "センチメント極性分布",
        yaxis=dict(
                title=dict(text='ー   ネガティブ ──── ポジティブ    +'),
                autorange=True,
                color = "gray",
                dtick=0,
                gridcolor='white',
                gridwidth=1,
                zerolinecolor='yellow',
                zerolinewidth=3,
                ),
    plot_bgcolor='rgba(64, 222, 69, .2)',
)


data = [trace0, trace1]
fig = go.Figure(data=data, layout=layout)

fig.update_yaxes(tickangle=0)
fig.add_hrect(y0=0, y1=-1.15, line_width=0, fillcolor="pink", opacity=0.5)

fig.show()

有料アプリと無料アプリのユーザー レビューのセンチメント極性スコアをプロットすると、負の Y 軸の外れ値が示すように、無料アプリが多くの厳しいコメントを受けていることがわかります。
有料アプリのレビューが極端に否定的になることはないようです。
これは、アプリの品質に関する何かを示している可能性があります。つまり、有料アプリは平均して無料アプリよりも高品質です。
有料アプリの極性スコアの中央値は無料アプリよりもわずかに高く、以前の観察と同期しています。


以上、Google Play ストアの 1 万以上のアプリを分析しました。
アプリを作成する場合、分析結果を使用して意思決定に役立てることができます。