はじめに
この記事では、今日のロシアのラップトップ市場の現状についてお話します。 Pythonコードを使用してすべての分析を実施します。 ラップトップを探している人と、Pythonで書くことを練習したい人の両方に役立つと思います。
始めましょう
分析のために、データセットが必要です。残念ながら、ロシアのオンラインラップトップストアでWebサービスを見つけることができなかったため、そのうちの1つの価格表をダウンロードし(名前は付けません)、価格と主要パラメーターを取得する必要がありました(私の意見では、これらは、プロセッサ周波数、モニターの対角線、RAMの容量、ハードディスクのサイズ、ビデオカードのメモリの容量です)。 次に、次の問題についていくつか分析を行いました。
- ラップトップの平均コスト
- ラップトップの平均的なハードウェア
- 最も高価/最も安いラップトップ構成
- どの構成パラメータが価格に最も影響するか
- 指定された構成の価格予測
- 構成と価格の分布のグラフ
コーディングしましょう
CSV形式で取得した価格表を保存しました。これを使用するには、csvモジュールを接続する必要があります。
CSVを インポート
再 インポート
ランダムに インポート
また、乱数と正規表現を操作するためのモジュールを接続しますが、これは後で必要になります。
次に、ラップトップを読み書きするためのメソッドを作成します。
def get_notebooks ():
reader = csv.reader( open ( 'data.csv' )、delimiter = ';' 、quotechar = '|' )
フィルターを返す ( ラムダ x:x != なし 、マップ(create_notebook、リーダー))
ここではすべてが簡単です。data.csvデータファイルを読み取り、create_notebook関数の結果でフィルタリングします。 価格のすべてのポジションがラップトップであるわけではありませんが、ところで、彼女は:
def create_notebook (生):
試してください :
ノートブック=ノートブック()
notebook.vendor = raw [0] .split( '' )[ 0 ]
notebook.model = raw [0] .split( '' )[ 1 ]
notebook.cpu = getFloat( r "(\ d +)\、(\ d +)\ s \" 、raw [ 0 ] .split( '/' )[ 0 ])
notebook.monitor = getFloat( r "(\ d +)\。(\ d +)\ ''" 、raw [ 0 ] .split( '/' )[ 1 ])
notebook.ram = getInt( r "(\ d +)\ Mb" 、raw [ 0 ] .split( '/' )[ 2 ])
notebook.hdd = getInt( r "(\ d +)Gb" 、raw [ 0 ] .split( '/' )[ 3 ])
notebook.video = getInt( r "(\ d +)Mb" 、raw [ 0 ] .split( '/' )[ 4 ])
notebook.price = getInt( r "(\ d +)\ s \ rub。" 、raw [ 1 ])
返却ノート
Exception を除き 、e:
何も返さない
ご覧のとおり、プロセッサのベンダー、モデル、およびタイプに注意を払わないことにしました(もちろん、ここではすべてがそれほど単純ではありませんが、それでもなお)、また、このメソッドにはカスタムヘルパー関数があります。
def getFloat (正規表現、生):
m = re.search(正規表現、生).groups()
return float(m [ 0 ] + '。' + m [1])
def getInt (正規表現、生):
m = re.search(正規表現、生).groups()
return int(m [ 0 ])
Pythonの記述は、OOP構造ではなくデータセットのスタイルで行うのが最適であることに注意してください。ただし、言語はこのスタイルにより適しているため、ドメインエリア(ラップトップ)に何らかの順序を持たせるために、次のようなクラスを導入しました上記に気付くかもしれません(ノートブック=ノートブック())
クラス ノートブック :
合格する
さて、これでメモリ内に構造ができて、分析の準備が整いました( 2005のさまざまな構成とそのコスト )。
ノートパソコンの平均価格:
def get_avg_price ():
print sum([n。get_notebooks()のnの価格)] / len (get_notebooks())
コードを実行すると、コンピューターの標準として1K $がまだ有効であることがわかります。
>> get_avg_price()
34574
ラップトップの平均的なハードウェア
def get_avg_parameters ():
"cpu {0}"を 印刷します 。 形式( sum ([n。get_notebooks()のnのcpu)) / len (get_notebooks()))
"monitor {0}"を 印刷します 。 format( sum ([n。get_notebooks()のnのモニター)) / len (get_notebooks()))
"ram {0}"を 印刷します 。 形式( sum ([n。get_notebooks()のnのram)) / len (get_notebooks()))
「hdd {0}」を 印刷します 。 フォーマット( sum ([n。get_notebooks()のnのhdd)) / len (get_notebooks()))
「ビデオ{0}」を 印刷します 。 format( sum ([n。get_notebooks()のnのビデオ) / len (get_notebooks()))
はい、そして私たちの手で平均化された構成:
>> get_avg_parameters()
CPU 2.0460798005
モニター14.6333167082
ラム2448
hdd 243
ビデオ289
最も高価/安価なラップトップ構成:
関数は、最小/最大関数を除いて同一です
def get_max_priced_notebook ():
maxprice = max ([n。get_notebooks()のnの価格))
maxconfig = filter ( lambda x:x。price == maxprice、get_notebooks())[0]
"cpu {0}"を 印刷します 。 フォーマット(maxconfig.cpu)
"monitor {0}"を 印刷します 。 フォーマット(maxconfig.monitor)
"ram {0}"を 印刷します 。 フォーマット(maxconfig.ram)
「hdd {0}」を 印刷します 。 フォーマット(maxconfig.hdd)
「ビデオ{0}」を 印刷します 。 フォーマット(maxconfig.video)
「価格{0}」を 印刷します 。 フォーマット(maxconfig.price)
>> get_max_priced_notebook()
CPU 2.26
モニター18.4
ラム4096
hdd 500
ビデオ1024
価格181660
>> get_min_priced_notebook()
CPU 1.6
モニター8.9
ラム512
hdd 8
ビデオ128
価格8090
どの構成パラメータが価格に最も影響するか
どの構成パラメーターに最もお金を払うかを知ることは非常に興味深いでしょう。 推定して、おそらくこれがモニターとプロセッサー周波数の対角線であると仮定しました、まあ、これをチェックする価値があると思います。
まず、構成パラメーターのセットを少し変更する必要があります。 さまざまなパラメーターの単位は順序が異なるという事実のため、それらを同じ分母に持っていく必要があります。 それらを正規化します。 それでは始めましょう:
def normalized_set_of_notebooks ():
notebooks = get_notebooks()
cpu = max ([n 。ノートブックのnのcpu])
monitor = max ([n 。ノートブックのnのモニター])
ram = max ([n 。ノートブックのnのram])
hdd = max ([n 。ノートブックのnのhdd])
video = max ([n 。ノートブックのnのビデオ])
rows = map ( lambda n:[n。cpu / cpu、n.monitor / monitor、 float (n。ram)/ ram、 float (n。hdd)/ hdd、 float (n。video)/ video、n.price ]、ノートブック)
行を返す
この関数では、各パラメーターの最大値を見つけます。その後、ラップトップの結果リストを作成します。各パラメーターは係数として示され(値は0から1まで変化します)、セット内の最大値に対するパラメーターの比率を示します。たとえば、2048Mbのメモリは、構成にram = 0.5(2048/4056)の係数を与えます。
ルーブルで考慮する各パラメーターの貢献度を明確にするために、これらの重みをセットに保存します。
#cpu、モニター、RAM、HDD、ビデオ
koes = [0、0、0、0、0]
各構成に対してこれらの係数を計算し、すべての係数の平均値を決定することをお勧めします。これにより、各構成要素の重みに関する平均データが得られます。
def analyze_params (パラメーター):
koeshistory = []
#ラップトップ
ノート= normalized_set_of_notebooks()
範囲内のi(len(注)):
koes = [0、0、0、0、0]
#係数を設定
set_koes(注[i]、koes)
#オッズ履歴を保存
koeshistory 。 拡張(koes)
#進捗状況を表示
if (i % 100 == 0):
印刷する
印刷ケーズ
各構成アイテムの係数はどのように設定しますか? 私の方法はこれです:
- いずれかの係数の値をランダムに増減する必要があります
- 次に、パラメータベクトルに係数ベクトルを掛けるときに、コンフィギュレーションの価格に近いかどうかを分析します(この場合はルーブルです)。
- 近似が行われた場合、このアクションを繰り返し、そうでない場合はキャンセルします
- 設定した精度で価格に近付かない範囲でこの注文を繰り返します
このアルゴリズムの実装は次のとおりです。
def set_koes (注、 koes 、エラー= 500):
価格= get_price(注、koes)
lasterror = abs (注[ 5 ]-価格)
while (lasterror > error):
k = random.randint(0,4)
#係数を変更
inc = (random.random()* 2-1)*(error *(1-error / lasterror))
koes [k] + = inc
#係数がゼロ未満にならないようにします
if (koes [k] < 0):koes [k] = 0
#係数を考慮すると価格が得られます
価格= get_price(注、koes)
#現在のエラーを取得
curerror = abs (注[ 5 ]-価格)
#価格表に表示されている価格に近いかどうかを確認する
if (lasterror < curerror):
koes [k]-= inc
その他 :
lasterror = curerror
incは、係数の増減に関与する変数です。計算方法は、この値が大きいほど、誤差の差が大きいほど、望ましい結果をより迅速かつ正確に近似する必要があるという事実によって説明されます。
価格を得るためのベクトルの乗算は次のとおりです。
def get_price (注、 koes ):
return sum([note [i] * koes [i] for i in range( 5 )]))
分析を行う時間です:
>> analyze_params()
CPU、モニター、RAM、HDD、ビデオ
[ 15455.60675667684、20980.560483811361、12782.535270304281、17819.904629585861、14677.889529808042 ]
各セットについて取得した係数を平均化することにより、このセットを取得しました。
def get_avg_koes (koeshistory):
koes = [0、0、0、0、0]
koeshistoryの行の場合:
範囲内のi( 5 ):
koes [i] + = koeshistory [i]
範囲内のi( 5 ):
koes [i] / = len (koeshistory)
返品
したがって、これらの数値から何を言うことができるかについて、目的のセットを取得しましたが、パラメーターの評価を行うことはできます。
- モニター対角線
- ハードディスクの空き容量
- CPU周波数
- ビデオカードのボリューム
- RAMサイズ
これは理想的なオプションとはほど遠いものであり、異なる結果が得られる可能性がありますが、プロセッサ周波数とディスプレイの対角線が構成で最も重要なパラメーターであるという私の仮定は部分的に確認されました。
指定された構成の価格予測
特定の構成の価格を予測できるような豊富なデータセットがあれば、それは素晴らしいことです。 これが私たちがやることです。
始めるために、ラップトップのコレクションをリストに変換します。
def get_notebooks_list ():
マップを返す ( ラムダ n:[n。cpu、n.monitor、n.ram、n.hdd、n.video、n.price]、get_notebooks())
次に、2つのベクトル間の距離を決定できる関数が必要です。ユークリッド距離関数は、良い選択肢です。
def ユークリッド (v1、v2):
d = 0.0
範囲内のi(len(v1)):
d + = (v1 [i]-v2 [i])** 2;
数学を返し ます。 sqrt(d)
差の二乗和の根は、あるベクトルが別のベクトルとどれだけ異なるかを非常に明確かつ効果的に示しています。 この機能は何に役立つのでしょうか? 簡単です。関心のあるパラメーターを持つベクトルを取得すると、セットのコレクション全体を調べて最も近い隣を見つけます。その値は既にわかっています。 方法は次のとおりです。
def getdistances (データ、vec1):
distancelist = []
範囲内のi(len(データ)):
vec2 =データ[i]
distancelist.append((ユークリッド(vec1、vec2)、i))
distancelist.sort()
距離リストを返す
さらに、提供されるデータの精度だけでなく、タスクを少し複雑にすることができます。 これを行うために、 k個の重み付き最近傍の方法による分類を使用して関数を導入します。
重み付き最近傍は、オブジェクトの類似性の評価に基づくメトリック分類アルゴリズムです。 分類されたオブジェクトは、最も近いトレーニングサンプルのオブジェクトが属するクラスに属します。
さて、いくつかの最近傍の平均値を取ります。これにより、ベンダーの価格や構成の特異性の影響が打ち消されます。
def knnestimate (データ、vec1、k = 3):
dlist = getdistances(データ、vec1)
平均= 0.0
範囲(k)のiの場合:
idx = dlist [i] [1]
平均+ =データ[idx] [5]
平均/ = k
平均を返す
*最後の3つのアルゴリズムは、 Segeran Tobyの著書「Programming the Collective Mind」から引用されています。
そして、私たちは何を得ます:
>> knnestimate(get_notebooks_list()、[2.4、17、3062、250、512])
31521.0
>> knnestimate(get_notebooks_list()、[2.0、15、2048、160、256])
27259.0
>> knnestimate(get_notebooks_list()、[2.0、15、2048、160、128])
20848.0
この実装では、プロセッサの周波数とモニターの対角線を絶対に考慮していませんが、価格は市場であり、これで十分です(このため、前の段落で計算した重みのベクトルを比較する機能に追加する必要があります)
構成と価格の分布のグラフ
配信画像全体、つまり、 市場での構成と価格の分布を描きます。 はい、やってみましょう。
まず、 matplotlibライブラリを配置する必要があります。 次に、プロジェクトに接続します。
pylab インポート から *
また、横座標と縦座標用に2つのデータセットを作成する必要があります。
def power_of_notebooks_config ():
マップを返す ( ラムダ x:x [ 0 ] * x [1] * x [2] * x [3] * x [4]、normalized_set_of_notebooks())
def config_prices ():
マップを返す ( ラムダ x:x [ 5 ]、normalized_set_of_notebooks())
そして、分布をプロットする関数:
def draw_market ():
plot(config_prices()、power_of_notebooks_config()、 'bo' 、linewidth = 1.0)
xlabel( 'price(Rub)' )
ylabel( 'config_power')
タイトル(「ロシアのノートブック市場」)
グリッド( True )
表示()
そして、私たちは何を得ます:
結論として
そこで、私たちはロシアのラップトップ市場の小さな分析を行い、Pythonを少し試してみました。
プロジェクトのソースコードは次の場所にあります。
http://code.google.com/p/runm/source/checkout
私のエンジン( pygments )がHabrに認識されることを望んでいなかったため、わずかに重要な構文の強調表示について謝罪します。