2017-05-28 12 views
1

年齢と性別の値に対する簡単な重み付けツールを作成しようとしています。スクリプトは、性別がどのように分布するかを調べ、それを所望の分布と比較し、それに応じて体重の列を更新する(例えば、1から1.12に行く)。次に、年齢が分布する方法を見て(新しく割り当てられた重みを念頭に置いて)、それを所望の分布と比較し、重みの列を再び更新する。データフレーム内の個々の値を個別に掛ける

最初のゴーラウンドはうまく動作しますが、2番目のステップでは機能しません。私は理由を知っていますが、修正する方法が失われています。それは最初の値を拾い上げ、それをボード全体に適用するように見えますが、実際には個々のセルを個別に評価する必要があります。

例として:最初のラウンドでは、女性細胞は.98、男性細胞は1.02になります。次に、年齢の重みを計算し、年齢値1を探します。最初の年齢= 1の値は女性です。次に、年齢値= 1の男性が実際に1.02と掛け合わされるにもかかわらず、すべての年齢= 1細胞について年齢= 1体重に.98を乗じます。

以下は、データのサブセットに対するmyスクリプトの完全版です。個々のセルを個別に評価するにはどうすればよいですか?

weightdict = {'Gender' : {1 : .49, 2 : .51}, 'Age' : {1 : 0.08, 2 : .27, 3 : .31, 4 : .34}} 
    weightframe = pd.DataFrame.from_dict(weightdict,orient='columns') 
    df = {'Gender': {0: 1, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 2, 7: 1, 8: 1, 9: 2}, 
    'Age': {0: 3, 1: 3, 2: 2, 3: 1, 4: 4, 5: 2, 6: 3, 7: 4, 8: 4, 9: 3}} 
    df = pd.DataFrame.from_dict(df,orient='columns') 
df.loc[:,'Weight'] = 1 #add a dummy weight column 

def getaverage(column): 
    average = df.groupby(column)['Weight'].sum()/df['Weight'].sum() #find distribution within dataset for each value 
    average = weightframe[column].div(average) #find what % the value is still under/overrepresented 
    average = average.reset_index() 
    average = average.rename(columns={'index' : 'variable',0 : column}) 
    return average 

def multiply(x): 
    value = df.loc[df[column]==x,column].iloc[0] #get value from table to evaluate 
    weight = df.loc[df[column]==value,'Weight'].iloc[0] #get the value's currently assigned weight 
    newvalue = average.loc[average['variable']==value, column].iloc[0] #get the value's degree of over/underrepresentation 
    return newvalue*weight #multiply the new weight by the old weight 

for column in list(df)[0:2]: 
    average = getaverage(column) #get set of averages for column 
    df['Weight'] = df[column].apply((lambda x : multiply(x))) 
    print(df) 
+0

'df'との内部' COLUMN' '()' *例外*悪い考えであるが適用されます。それを修正し、あなたの問題が魔法のように消えるかどうかを提案してください。もしそうでなければ、この記事をより良いコードと期待される結果で[MCVE](https://stackoverflow.com/help/mcve)の形で更新することをお勧めします。 –

+0

私は「より良い」コードを投稿したいと思いますが、私はPythonにはまだ新しく、なぜそれが悪い習慣であるのか(あるいは違ったやり方で、何故私が投稿したのか)はわかりません。あなたが精緻化したらそれは助けになるだろうか? – oddnumberedcat

+0

グローバル変数とローカル変数の概念を理解していますか? –

答えて

0

最終出力に含めるべき内容を正確に理解するのは難しいですが、何か助けてもらえると思います。あなたのDFと重みを皮切り

、私は(私は今のダミーウェイト列をオフに左)のようになりますテーブルを取得:

weightdict = { 
       'Gender': {1: 0.49, 2: 0.51}, 
        'Age': {1: 0.08, 2: 0.27, 3 : .31, 4 : .34} 
       } 
weightframe = pd.DataFrame.from_dict(weightdict,orient='columns') 

df = { 
     'Gender': {0: 1, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 2, 7: 1, 8: 1, 9: 2}, 
     'Age': {0: 3, 1: 3, 2: 2, 3: 1, 4: 4, 5: 2, 6: 3, 7: 4, 8: 4, 9: 3} 
    } 
df = pd.DataFrame.from_dict(df,orient='columns') 

df 

Out[]: 
    Age Gender 
0 3  1 
1 3  2 
2 2  2 
3 1  1 
4 4  2 
5 2  1 
6 3  2 
7 4  1 
8 4  1 
9 3  2 

することができます、その後AgeGender列をループして作成しますそれぞれの重みを表す新しい列:

for col in df[0:2]: 
    # create a dict (printed for clarity) with the calculated weight 
    # for each entry to feed to the following `map` statements 
    dist = {idx: count/len(df) for idx, count in df[col].value_counts().items()} 
    print(col) 
    print(dist) 
    df[col + 'Weight'] = df[col].map(weightdict[col])/df[col].map(dist) 

df 

----- 
Age 
{3: 0.40000000000000002, 4: 0.29999999999999999, 
2: 0.20000000000000001, 1: 0.10000000000000001} 
Gender 
{2: 0.5, 1: 0.5} 

たDFは次のようになります。

Out[]: 
    Age Gender AgeWeight GenderWeight 
0 3  1 0.775000   0.98 
1 3  2 0.775000   1.02 
2 2  2 1.350000   1.02 
3 1  1 0.800000   0.98 
4 4  2 1.133333   1.02 
5 2  1 1.350000   0.98 
6 3  2 0.775000   1.02 
7 4  1 1.133333   0.98 
8 4  1 1.133333   0.98 
9 3  2 0.775000   1.02 

これで、行全体で計算を実行できます。私はあなたが望む実際の計算であるかどうかはわかりませんが、あなたはこのアプローチに適応できるはずです。

df['Weighted'] = df.AgeWeight * df.GenderWeight 

df 

Out[16]: 
    Age Gender AgeWeight GenderWeight Weighted 
0 3  1 0.775000   0.98 0.759500 
1 3  2 0.775000   1.02 0.790500 
2 2  2 1.350000   1.02 1.377000 
3 1  1 0.800000   0.98 0.784000 
4 4  2 1.133333   1.02 1.156000 
5 2  1 1.350000   0.98 1.323000 
6 3  2 0.775000   1.02 0.790500 
7 4  1 1.133333   0.98 1.110667 
8 4  1 1.133333   0.98 1.110667 
9 3  2 0.775000   1.02 0.790500 

クリーンアップDF:関数の乗算は、グローバル変数を使用している

del df['AgeWeight'] 
del df['GenderWeight'] 

df 

Out[12]: 
    Age Gender Weighted 
0 3  1 2.278500 
1 3  2 2.371500 
2 2  2 2.754000 
3 1  1 0.784000 
4 4  2 4.624000 
5 2  1 2.646000 
6 3  2 2.371500 
7 4  1 4.442667 
8 4  1 4.442667 
9 3  2 2.371500 
関連する問題