問題

私はPythonプログラミングの初心者ですが、これを達成したSOソリューションはありませんでした。

私は、CSVを開き、列内のすべての値を平均化し、その列の平均値を格納するPythonプログラムを作成しようとしています。次に、値がその平均以上の場合は、値を1に変更し、下の場合は0に変更します。以下は私が意味することの説明です:

 | 2  | 5  | 11 | 2  |
| 0  | 7  | 8  | 11 |
| 22 | 55 | 4  | 3  |
| 0  | 2  | 8  | 7  |
 

次のような平均があります:Col[0] = 6, Col[1] = 17, Col[2] = 8, Col[3] = 6
または 次に、テーブルは次のように変更されます。

 | 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 |
| 1 | 1 | 0 | 0 |
| 0 | 0 | 1 | 1 |
 

私はコード書き込みサービスを求めていませんが、私はこれに非常に新しいです。私は擬似コードが次のようになると思います:

 average_columns(csv myFile){
    for each column in csv:
        average = sum(column) / len(column)
        for each row in column:
            if row.value >= average{
                row.value = 1
            }else{
                row_value = 0
            }
}
 

誰にもこのアプローチに関するアイデアはありますか?

ありがとうございました

  ベストアンサー

純粋なPython(つまり、パンダのようなライブラリを使用しない)では、実装はおそらくテーブル全体を2回ループします。データセットのサイズに応じて、全体をロードしてから結果を2回処理することができます。サイズがわからないので、後者のアプローチは最も安全です。

 import csv

with open('input.csv', 'r') as inf:
    # setting the quoting causes the reader to interpret non-quoted values as floats
    cr = csv.reader(inf, quoting=csv.QUOTE_NONNUMERIC)
    # initialise sums to the first line, assumes there's at least one line
    sums = next(cr)
    n = 0
    # add all the other lines, one by one
    for row in cr:
        n += 1
        sums = [x + y for x, y in zip(sums, row)]
    # calculate averages from the sums
    averages = [x / n for x in sums]

# second loop over the input, writing the result to output
with open('input.csv', 'r') as inf:
    with open('output.csv', 'w', newline='') as outf:
        cr = csv.reader(inf, quoting=csv.QUOTE_NONNUMERIC)
        cw = csv.writer(outf)
        for row in cr:
            cw.writerow([1 if x > a else 0 for x, a in zip(row, averages)])
 

input.csv:

 1,2,3,4
5,6,7,8
1,2,3,4
1,6,'blah',8
1,1,1,1
 

結果のoutput.csv:

 0,0,0,0
1,1,1,1
0,0,0,0
0,1,0,1
0,0,0,0
 

データに非浮動小数点値が含まれている場合は、これらを処理する必要があり、1つの方法は値0を割り当てることです。

 import csv


def safe_float(x):
    try:
        return float(x)
    except ValueError:
        return 0


with open('data.csv', 'r') as inf:
    cr = csv.reader(inf)
    sums = [safe_float(x) for x in next(cr)]
    n = 0
    for row in cr:
        float_row = [safe_float(x) for x in row]
        sums = [x + y for x, y in zip(sums, float_row)]
        n += 1
    averages = [x / n for x in sums]

with open('data.csv', 'r') as inf:
    with open('output.csv', 'w', newline='') as outf:
        cr = csv.reader(inf)
        cw = csv.writer(outf)
        for row in cr:
            float_row = [safe_float(x) for x in row]
            cw.writerow([1 if x > a else 0 for x, a in zip(float_row, averages)])
 

各反復で合計が上書きされるのが好きでない場合は、次のように置き換えることができます。

 sums = [x + y for x, y in zip(sums, float_row)]
 

〜と:

 for i in range(len(sums)):
    sums[i] += float_row[i]
 

そしてもちろん、ループの外で一度設定することで長さを計算することは避けることができます。より多くのoptimisationは常に可能ですが、コードを簡単にするか、最適に実行するかどうかは本当にあなたのニーズに依存します。

  同じタグがついた質問を見る

pythonpython-3.x