質問するログイン新規登録

Q&A

解決済

3回答

460閲覧

リスト内包表記の中でのif文の使用の仕方が分かりません

yyicp

総合スコア104

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

1グッド

1クリップ

投稿2026/02/10 04:59

1

1

実現したいこと

test2.csvは以下のようなファイルです。

t x y 0 10 20 1 11 21 2 12 22 3 13 23

今、t≦1のときz=x、t>1のときz=y、と定義したzの値をyの右側に加えたいです。
つまり、欲しい結果は以下の通りです。

t x y z 0 10 20 10 1 11 21 11 2 12 22 22 3 13 23 23

「該当のソースコード」ではエラーが出てしまいました。どなたかコードを直してください。

発生している問題・エラーメッセージ

Traceback (most recent call last): File "〇〇〇\testCV659teratail2.py", line 5, in <module> df['z'] = [(b if df['t'] > 1 else a) for a, b in zip(df['x'], df['y'])] ^^^^^^^^^^^ File "〇〇〇\site-packages\pandas\core\generic.py", line 1580, in __nonzero__ raise ValueError( ...<2 lines>... ) ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

該当のソースコード

python

1import pandas as pd 2 3df = pd.read_csv('test2.csv') 4 5df['z'] = [(b if df['t'] > 1 else a) for a, b in zip(df['x'], df['y'])] 6 7print(df)

試したこと

zip関数に慣れていなくて、よく分かりませんでした。

googleのAIによる下記のコードを参考にしました。

python

1list_a = [0, 1, 2, 3] 2list_b = [10, 20, 30, 40] 3 4# t (a) > 1 なら b*2、そうでなければ b のままにする 5result = [(a, b * 2 if a > 1 else b) for a, b in zip(list_a, list_b)] 6 7print(result) 8# 出力: [(0, 10), (1, 20), (2, 60), (3, 80)]
melian👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

guest

回答3

0

既に解決済みなので御参考です。

今回のケースでは,既に回答されているように numpy の where() 関数や pandas の where() メソッド,mask() メソッド などを用いるのが簡明で処理時間も短くなります。

一方,リスト内包表記のように行内の計算式がわかる記述をしたいのであれば,apply() メソッドaxis=1 とともに用いる方法も考えられますが,処理時間については(追記)を参照ください。

記述例を下記に示します。

Python

1import pandas as pd 2 3df = pd.DataFrame({'t': [0, 1, 2, 3], 4 'x': [10, 11, 12, 13], 5 'y': [20, 21, 22, 23]}) 6 7# df['z'] = df['x'].mask(df['t'] > 1, df['y']) 8df['z'] = df.apply(lambda r: r['y'] if r['t'] > 1 else r['x'], axis=1) 9 10print(df) 11# t x y z 12# 0 0 10 20 10 13# 1 1 11 21 11 14# 2 2 12 22 22 15# 3 3 13 23 23

(追記)

行数を10万行に増やして処理時間を比較をしてみたところ,apply() メソッドはリスト内包表記よりもかなり遅いようです(上記回答は一部訂正しました)。なお,環境は「macOS(M1)15.7.3,Python 3.13.11,pandas 3.0.0」です。

mask() メソッド: 0.0012 s
リスト内包表記: 0.0277 s
apply() メソッド: 0.2940 s

Python

1import pandas as pd 2import time 3 4n = 100000 5 6df = pd.DataFrame({'t': list(range(0, n)), 7 'x': list(range(10, n + 10)), 8 'y': list(range(20, n + 20))}) 9 10start = time.perf_counter() 11 12# df['z'] = df['x'].mask(df['t'] > 1, df['y']) 13# df['z'] = [y if t > 1 else x for t, x, y in zip(df['t'], df['x'], df['y'])] 14df['z'] = df.apply(lambda r: r['y'] if r['t'] > 1 else r['x'], axis=1) 15 16end = time.perf_counter() 17print(f'{(end - start):.4f} s')

投稿2026/02/11 07:03

編集2026/02/12 09:59
little_street

総合スコア553

yyicp

2026/02/12 01:03

できました。 どうもありがとうございました。
little_street

2026/02/12 07:19

回答に正しくない部分がありました。 処理時間を比較してみたところ apply() メソッドはリスト内包表記よりかなり遅いようです。比較方法などは(追記)を参照ください。
yyicp

2026/02/13 00:52

追記ありがとうございました。
guest

0

Windows 11、Python 3.14.2で確認しました。

以前の質問と同様にNumpyは不要です。

Python

1df['z'] = df['y'].where(df['t'] > 1, df['x'])

投稿2026/02/10 14:17

hiroki-o

総合スコア1749

melian

2026/02/10 15:51

一応補足しておきますと、実際には Pandas の内部で Numpy パッケージがインポートされています。 pandas/pandas/core/generic.py at v3.0.0 · pandas-dev/pandas https://github.com/pandas-dev/pandas/blob/v3.0.0/pandas/core/generic.py#L27 インポートされた Numpy パッケージは pandas.core.generic.np でアクセスすることができます。また、"import pandas as pd" を実行した後で Numpy パッケージをインポートすると("import numpy as np")、既にインポートされている Numpy パッケージに "np" というエイリアス名がバインドされることになります。(以下に示す通り、メモリアドレスが同一であることが判るかと思います) >>> import pandas as pd >>> id(pd.core.generic.np) 127039880300240 >>> import numpy as np >>> id(np) 127039880300240 >>> id(pd.core.generic.np) == id(np) True なので、以下の様に書くこともできるわけです。 import pandas as pd np = pd.core.generic.np df = pd.read_csv('test2.csv') df['z'] = np.where(df['t'] > 1, df['y'], df['x']) なお、numpy.where() を利用したのは、個人的には C の ternary operator(三項演算子)の様に読めるので判別しやすいと感じているからです。
hiroki-o

2026/02/10 16:16

解説ありがとうございます。 ということは、pandasのwhereとnumpyのwhereは内部で共通処理なのでしょうか。 それは暇があったらソースを見てみます。 どちらにしても、私はシンプルな書き方のほうが好きなので、pandasのwhereで回答しました。
yyicp

2026/02/12 01:04

できました。 どうもありがとうございました。
guest

0

ベストアンサー

以前の質問と同様に numpy.where() を使います。

python

1import pandas as pd 2import numpy as np 3 4df = pd.read_csv('test2.csv') 5 6df['z'] = np.where(df['t'] > 1, df['y'], df['x']) 7 8print(df) 9 10# t x y z 11# 0 0 10 20 10 12# 1 1 11 21 11 13# 2 2 12 22 22 14# 3 3 13 23 23

追記

List comprehension を使う場合は df['t'] もループ変数(t)に割り当てます。

python

1import pandas as pd 2import numpy as np 3 4df = pd.read_csv('test2.csv') 5 6df['z'] = [(b if t > 1 else a) for t, a, b in zip(df['t'], df['x'], df['y'])] 7 8print(df)

投稿2026/02/10 05:05

編集2026/02/10 05:10
melian

総合スコア21695

yyicp

2026/02/10 05:08

できました。 どうもありがとうございました。
yyicp

2026/02/10 05:22

追記の部分もできました。 どうもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.29%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問