はじめに
リスト内の要素を処理するのは一般的なタスクです。このセクションでは、そのための強力なツールであるリスト内包表記について説明します。
This tutorial is from open-source community. Access the source code
💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください
リスト内の要素を処理するのは一般的なタスクです。このセクションでは、そのための強力なツールであるリスト内包表記について説明します。
リスト内包表記は、シーケンスの各要素に演算を適用することで新しいリストを作成します。
>>> a = [1, 2, 3, 4, 5]
>>> b = [2*x for x in a ]
>>> b
[2, 4, 6, 8, 10]
>>>
別の例:
>>> names = ['Elwood', 'Jake']
>>> a = [name.lower() for name in names]
>>> a
['elwood', 'jake']
>>>
一般的な構文は:[ <式> for <変数名> in <シーケンス> ]
です。
リスト内包表記の間でフィルタリングもできます。
>>> a = [1, -5, 4, 2, -2, 10]
>>> b = [2*x for x in a if x > 0 ]
>>> b
[2, 8, 4, 20]
>>>
リスト内包表記は非常に便利です。たとえば、特定の辞書フィールドの値を収集することができます。
stocknames = [s['name'] for s in stocks]
シーケンスに対してデータベースのようなクエリを実行することができます。
a = [s for s in stocks if s['price'] > 100 and s['shares'] > 50 ]
また、リスト内包表記とシーケンスの集約を組み合わせることもできます。
cost = sum([s['shares']*s['price'] for s in stocks])
[ <式> for <変数名> in <シーケンス> if <条件>]
これが意味するところは:
result = []
for variable_name in sequence:
if condition:
result.append(式)
リスト内包表記は数学(集合記法)に由来しています。
a = [ x * x for x in s if x > 0 ] ## Python
a = { x^2 | x ∈ s, x > 0 } ## 数学
他のいくつかの言語でも実装されています。ただし、ほとんどのコーダーはおそらく数学の授業を思い出していません。ですから、これをクールなリストのショートカットと見なしても構いません。
シンタックスに慣れるために、いくつかの簡単なリスト内包表記を試してみましょう。
>>> nums = [1,2,3,4]
>>> squares = [ x * x for x in nums ]
>>> squares
[1, 4, 9, 16]
>>> twice = [ 2 * x for x in nums if x > 2 ]
>>> twice
[6, 8]
>>>
リスト内包表記がどのようにデータを適切に変換またはフィルタリングして新しいリストを作成しているかに注目してください。
シングルなPython文を使ってポートフォリオの総コストを計算しましょう。
>>> portfolio = read_portfolio('portfolio.csv')
>>> cost = sum([ s['shares'] * s['price'] for s in portfolio ])
>>> cost
44671.15
>>>
それができたら、シングルな文を使ってポートフォリオの現在の価値をどのように計算できるかを示してください。
>>> value = sum([ s['shares'] * prices[s['name']] for s in portfolio ])
>>> value
28686.1
>>>
上記の両方の操作は、マップ・リダクションの例です。リスト内包表記は、リスト全体に対して操作をマッピングしています。
>>> [ s['shares'] * s['price'] for s in portfolio ]
[3220.0000000000005, 4555.0, 12516.0, 10246.0, 3835.1499999999996, 3254.9999999999995, 7044.0]
>>>
次に、sum()
関数が結果全体に対して集約を行っています。
>>> sum(_)
44671.15
>>>
この知識を身につけることで、今やビッグデータのスタートアップ企業を立ち上げる準備が整いました。
さまざまなデータ照会の例を次のように試してみましょう。
まず、100株を超えるすべてのポートフォリオ保有株のリストです。
>>> more100 = [ s for s in portfolio if s['shares'] > 100 ]
>>> more100
[{'price': 83.44, 'name': 'CAT','shares': 150}, {'price': 51.23, 'name': 'MSFT','shares': 200}]
>>>
MSFTとIBMの株に関するすべてのポートフォリオ保有株。
>>> msftibm = [ s for s in portfolio if s['name'] in {'MSFT','IBM'} ]
>>> msftibm
[{'price': 91.1, 'name': 'IBM','shares': 50}, {'price': 51.23, 'name': 'MSFT','shares': 200},
{'price': 65.1, 'name': 'MSFT','shares': 50}, {'price': 70.44, 'name': 'IBM','shares': 100}]
>>>
10000ドル以上のコストがかかるすべてのポートフォリオ保有株のリスト。
>>> cost10k = [ s for s in portfolio if s['shares'] * s['price'] > 10000 ]
>>> cost10k
[{'price': 83.44, 'name': 'CAT','shares': 150}, {'price': 51.23, 'name': 'MSFT','shares': 200}]
>>>
name
とshares
がportfolio
から取得される、タプル(name, shares)
のリストをどのように作成できるかを示しましょう。
>>> name_shares =[ (s['name'], s['shares']) for s in portfolio ]
>>> name_shares
[('AA', 100), ('IBM', 50), ('CAT', 150), ('MSFT', 200), ('GE', 95), ('MSFT', 50), ('IBM', 100)]
>>>
四角かっこ([
, ]
)を波かっこ({
, }
)に変えると、セット内包表記と呼ばれるものが得られます。これにより、一意または異なる値が得られます。
たとえば、portfolio
に現れる一意の株式名のセットを決定します。
>>> names = { s['name'] for s in portfolio }
>>> names
{ 'AA', 'GE', 'IBM', 'MSFT', 'CAT' }
>>>
key:value
ペアを指定すると、辞書を作成できます。たとえば、株式の名前を保有株式の総数にマッピングする辞書を作成します。
>>> holdings = { name: 0 for name in names }
>>> holdings
{'AA': 0, 'GE': 0, 'IBM': 0, 'MSFT': 0, 'CAT': 0}
>>>
後者の機能は辞書内包表記と呼ばれます。表にまとめましょう。
>>> for s in portfolio:
holdings[s['name']] += s['shares']
>>> holdings
{ 'AA': 100, 'GE': 95, 'IBM': 150, 'MSFT':250, 'CAT': 150 }
>>>
prices
辞書を、ポートフォリオに現れる名前のみに絞り込むこの例を試してみましょう。
>>> portfolio_prices = { name: prices[name] for name in names }
>>> portfolio_prices
{'AA': 9.22, 'GE': 13.48, 'IBM': 106.28, 'MSFT': 20.89, 'CAT': 35.46}
>>>
リスト、セット、辞書内包表記のさまざまな組み合わせをどのように使うかを知ることは、さまざまな形式のデータ処理に役立ちます。ここでは、CSVファイルから選択された列を抽出する方法を示す例を紹介します。
まず、CSVファイルからヘッダー情報の1行を読み取ります。
>>> import csv
>>> f = open('portfoliodate.csv')
>>> rows = csv.reader(f)
>>> headers = next(rows)
>>> headers
['name', 'date', 'time','shares', 'price']
>>>
次に、実際に関心のある列をリストに格納する変数を定義します。
>>> select = ['name','shares', 'price']
>>>
次に、上記の列がソースCSVファイルのどのインデックスにあるかを特定します。
>>> indices = [ headers.index(colname) for colname in select ]
>>> indices
[0, 3, 4]
>>>
最後に、1行のデータを読み取り、辞書内包表記を使って辞書に変換します。
>>> row = next(rows)
>>> record = { colname: row[index] for colname, index in zip(select, indices) } ## dict-comprehension
>>> record
{'price': '32.20', 'name': 'AA','shares': '100'}
>>>
これまでのことが分かりやすければ、ファイルの残りを読み取りましょう。
>>> portfolio = [ { colname: row[index] for colname, index in zip(select, indices) } for row in rows ]
>>> portfolio
[{'price': '91.10', 'name': 'IBM','shares': '50'}, {'price': '83.44', 'name': 'CAT','shares': '150'},
{'price': '51.23', 'name': 'MSFT','shares': '200'}, {'price': '40.37', 'name': 'GE','shares': '95'},
{'price': '65.10', 'name': 'MSFT','shares': '50'}, {'price': '70.44', 'name': 'IBM','shares': '100'}]
>>>
まあ、あなたはちょうどread_portfolio()
関数の多くを1つの文にまとめました。
リスト内包表記は、Pythonでデータを変換、フィルタリング、または収集するための効率的な手段として一般的に使用されます。構文のため、やりすぎにはならないでください。各リスト内包表記をできるだけ簡単に保つようにしましょう。複数のステップに分けるのも大丈夫です。たとえば、最後の例を不意に同僚に投げかけるのが良いことかどうかは明確ではありません。
とはいえ、データを迅速に操作する方法を知ることは、非常に役立つスキルです。データのインポート、エクスポート、抽出などを含むある種の一回限りの問題を解かなければならない状況は数多くあります。リスト内包表記の達人になることで、解決策を考えるのに費やされる時間を大幅に短縮できます。また、collections
モジュールを忘れないでください。
おめでとうございます!あなたはリスト内包表記の実験を完了しました。あなたのスキルを向上させるために、LabExでさらに実験を行って練習することができます。