2

データをヒストグラム タイプのデータにグループ化するこのコードを受け取りました。この pandas スクリプトのコードを編集、操作、複製するために理解しようとしています。私が理解しているセクションについてコメントがあります。

コード

import numpy as np
import pandas as pd


column_names = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6', 
              'col7', 'col8', 'col9', 'col10', 'col11'] #names to be used as column labels.  If no names are specified then columns can be refereed to by number eg. df[0], df[1] etc.

df = pd.read_csv('data.csv', header=None, names=column_names) #header= None means there are no column headings in the  csv file

df.ix[df.col11 == 'x', 'col11']=-0.08 #trick so that 'x' rows will be grouped into a category >-0.1 and <= -0.05.  This will allow all of col11 to be treated as a numbers

bins = np.arange(-0.1, 1.0, 0.05) #bins to put col11 values in.  >-0.1 and <=-0.05 will be our special 'x' rows, >-0.05 and <=0 will capture all the '0' values.
labels = np.array(['%s:%s' % (x, y) for x, y in zip(bins[:-1], bins[1:])]) #create labels for the bins
labels[0] = 'x' #change first bin label to 'x'
labels[1] = '0' #change second bin label to '0'

df['col11'] = df['col11'].astype(float) #convert col11 to numbers so we can do math on them


df['bin'] = pd.cut(df['col11'], bins=bins, labels=False) # make another column 'bins' and put in an integer representing what bin the number falls into.Later we'll map the integer to the bin label


df.set_index('bin', inplace=True, drop=False, append=False) #groupby is meant to run faster with an index

def count_ones(x):
    """aggregate function to count values that equal 1"""
    return np.sum(x==1)

dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [count_ones, len]})
dfg.index = labels[dfg.index]

dfg.ix['x',('col11', 'mean')]='N/A'
print(dfg)
dfg.to_csv('new.csv')

私が本当に理解するのに苦労しているセクションは、このセクションにあります。

def count_ones(x):
    """aggregate function to count values that equal 1"""
    return np.sum(x==1)

dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [count_ones, len]})
dfg.index = labels[dfg.index]

dfg.ix['x',('col11', 'mean')]='N/A'
print(dfg)
dfg.to_csv('new.csv')

誰かがこのスクリプトにコメントできるなら、私は大いに感謝します. また、私のコメントを修正または追加してください(これらは、これまでのところ、正しくない可能性があると想定しています)。これがSOFの話題から外れていないことを願っています。これを手伝ってくれるユーザーには喜んで 50 ポイントの報奨金を差し上げます。

4

1 に答える 1

8

私は自分のコードを説明しようとします。いくつかのトリックを使用するため。

  • dfpandas DataFrame の短縮名を付けるために呼び出しました
  • dfgグループ my を意味するためにそれを呼び出しましたdf
  • 表現を組み立てようdfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [count_ones, len]})

    • コードdfg = df[['bin','col7','col11']]は、私の DataFrame から 'bin' 'col7' および 'col11' という名前の列を取得すると言っていますdf
    • 関心のある 3 つの列ができたので、「bin」列の値でグループ化します。これは によって行われdfg = df[['bin','col7','col11']].groupby('bin')ます。これで、データのグループ、つまりビン #1 にあるすべてのレコード、ビン #2 にあるすべてのレコードなどがあります。
    • 各ビングループのレコードにいくつかの集計関数を適用したいと思います(集計関数は、合計、平均、またはカウントのようなものです)。
    • ここで、各ビンのレコードに 3 つの集計関数を適用します。「col11」の平均、各ビンのレコード数、および「col7」が 1 に等しい各ビンのレコード数です。平均は簡単です。numpy にはすでに平均を計算する関数があります。'col11' の平均値を計算するだけなら、次のように書きます dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean]})。レコード数も簡単です。Pythonのlen関数(実際には関数ではなく、リストなどのプロパティです)は、リスト内のアイテムの数を提供します。だから私は今持っていdfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [len]})ます。現在、numpy 配列内の 1 の数をカウントする既存の関数は考えられません (numpy 配列で動作する必要があります)。numpy 配列で機能する独自の関数を定義できるため、 my function count_ones.
    • 次に、関数を分解しcount_onesます。関数に渡される変数xは、常に 1 次元の numpy 配列になります。特定のケースでは、bin#1 に含まれるすべての「col7」値、bin#2 に含まれるすべての「col7」値などになります。コードx==1は、同じサイズのブール (TRUE/FALSE) 配列を作成します。 ×として。ブール配列のエントリは、x の対応する値が 1 に等しい場合は True になり、それ以外の場合は false になります。ブール配列の値を合計すると、Python は True を 1 として扱うため、==1 の値のカウントが得られます。関数ができたので、count_ones次のようにして「col7」に適用します。dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [count_ones, len]})

    • の構文.agg.agg({'column_name_to_apply_to': [list_of_function names_to_apply]}

    • ブール配列を使用すると、あらゆる種類の奇妙な条件の組み合わせを実行できます (x==6) | (x==3) は、「x = 6 または x = 3」になります。「and」演算子は & です。常に()各条件を配置する

  • dfg.index = labels[dfg.index]。ではdfg、「ビン」でグループ化したため、グループ化されたデータ (つまり、dfg.index) の各行のインデックス (または行ラベル) がビン番号になります:1,2,3, labels[dfg.index]numpy 配列の派手なインデックス付けを使用しています. labels[0] は最初のラベルを与え、labels[3] は 4 番目のラベルを与えます。通常の python リストでは、スライスを使用してラベル [0:3] を実行できます。これにより、ラベル 0、1、および 2 が得られます。numpy 配列を使用すると、さらに一歩進んで、値のリストまたは別の配列でインデックスを付けてラベルを付けることができます。 [np.array([0,2,4]) はラベル 0,2,4 を与えます。使用することでlabels[dfg.index]bin# に対応するラベルをリクエストしています。基本的に、ビン番号をビンラベルに変更しています。元のデータにそれを行うこともできましたが、それは何千行にもなります。group by の後に行うことで、21 行程度まで行っています。dfg.index = labels一部のビンが空で、データによるグループに存在しない可能性があるため、私はできないことに注意してください。

  • 今、そのdfg.ix['x',('col11', 'mean')]='N/A'部分。df.ix[df.col11 == 'x', 'col11']=-0.08無効なデータはすべて数値として扱われ、1 番目のビンに配置されていました。group by および集計関数を適用した後、最初のビンの「col11」値の平均は -0.08 になります (そのような値はすべて -0.08 であるため)。これが正しくないことがわかりました。-0.08 のすべての値は、実際には元の値が x であったことを示しています。x の平均を計算することはできません。そこで、手動で N/A にしました。すなわち。dfg.ix['x',('col11', 'mean')]='N/A'インデックス (または行) が 'x' で列が 'col11 mean' である dfg の平均) は、値を 'N/A' に設定します。私が信じているのは、('col11', 'mean')パンダが集計列の名前を思いつく方法です。つまり、私がしたとき.agg({'col11': [np.mean]})、必要な結果の集計列を参照するために('column_name', 'aggregate_function_name')

このすべての動機は、すべてのデータを数値に変換して Pandas の機能を利用できるようにし、処理後にゴミであることがわかっている値を手動で変更することでした。さらに説明が必要な場合はお知らせください。

于 2013-11-05T11:01:17.327 に答える