質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

88.78%

pandasで、特定の列、行でフィルタリングしたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 686

H.Ka2

score 42

前提・実現したいこと

python 3.6系で、pandasのdataframeを使って、特定の列(list)と、特定の列の値がいくら以上(辞書(列名:条件(xx以上)))という条件でフィルタリングして、結果のdfを返す関数を作りたいです。
イメージは下記のようなものとなります。dictのkey(列名)と、listの列名は、
集合としては、listのほうが大きい(もしくは等しい)です。(まずlistでフィルタして、その中で、辞書でフィルタする感じ)
イメージ説明

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

上記を作ろうと思い、コードを描いてみたのですが、下記エラーが発生します。
「k」(辞書のkey)は存在するのにdefineされてないと出て、「???」となっています。。。
非常に基礎的なことで引っかかっているような気もして、質問するのも申し訳ありませんが、ご教示いただけますと幸甚に存じます。

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\scope.py in resolve(self, key, is_local)
    180             if self.has_resolvers:
--> 181                 return self.resolvers[key]
    182 

C:\ProgramData\Anaconda3\lib\collections\__init__.py in __getitem__(self, key)
    882                 pass
--> 883         return self.__missing__(key)            # support subclasses that define __missing__
    884 

C:\ProgramData\Anaconda3\lib\collections\__init__.py in __missing__(self, key)
    874     def __missing__(self, key):
--> 875         raise KeyError(key)
    876 

KeyError: 'k'

During handling of the above exception, another exception occurred:

KeyError                                  Traceback (most recent call last)
C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\scope.py in resolve(self, key, is_local)
    191                 # e.g., df[df > 0]
--> 192                 return self.temps[key]
    193             except KeyError:

KeyError: 'k'

During handling of the above exception, another exception occurred:

UndefinedVariableError                    Traceback (most recent call last)
<ipython-input-21-77582b1647bc> in <module>()
----> 1 df2 = filter_df(df, {'列1':9, '列2':15}, ['列1', '列2'])

<ipython-input-20-393068bc75a5> in filter_df(src_df, dict_row, lst_col)
      4     ret_df = src_df[lst_col]
      5     for k, v in dict_row.items():
----> 6         print(ret_df.query('k > @v'))
      7 
      8     return ret_df

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py in query(self, expr, inplace, **kwargs)
   2845         kwargs['level'] = kwargs.pop('level', 0) + 1
   2846         kwargs['target'] = None
-> 2847         res = self.eval(expr, **kwargs)
   2848 
   2849         try:

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py in eval(self, expr, inplace, **kwargs)
   2960             kwargs['target'] = self
   2961         kwargs['resolvers'] = kwargs.get('resolvers', ()) + tuple(resolvers)
-> 2962         return _eval(expr, inplace=inplace, **kwargs)
   2963 
   2964     def select_dtypes(self, include=None, exclude=None):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\eval.py in eval(expr, parser, engine, truediv, local_dict, global_dict, resolvers, level, target, inplace)
    289 
    290         parsed_expr = Expr(expr, engine=engine, parser=parser, env=env,
--> 291                            truediv=truediv)
    292 
    293         # construct the engine and evaluate the parsed expression

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in __init__(self, expr, engine, parser, env, truediv, level)
    737         self.env.scope['truediv'] = truediv
    738         self._visitor = _parsers[parser](self.env, self.engine, self.parser)
--> 739         self.terms = self.parse()
    740 
    741     @property

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in parse(self)
    754     def parse(self):
    755         """Parse an expression"""
--> 756         return self._visitor.visit(self.expr)
    757 
    758     @property

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs)
    319         method = 'visit_' + node.__class__.__name__
    320         visitor = getattr(self, method)
--> 321         return visitor(node, **kwargs)
    322 
    323     def visit_Module(self, node, **kwargs):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit_Module(self, node, **kwargs)
    325             raise SyntaxError('only a single expression is allowed')
    326         expr = node.body[0]
--> 327         return self.visit(expr, **kwargs)
    328 
    329     def visit_Expr(self, node, **kwargs):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs)
    319         method = 'visit_' + node.__class__.__name__
    320         visitor = getattr(self, method)
--> 321         return visitor(node, **kwargs)
    322 
    323     def visit_Module(self, node, **kwargs):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit_Expr(self, node, **kwargs)
    328 
    329     def visit_Expr(self, node, **kwargs):
--> 330         return self.visit(node.value, **kwargs)
    331 
    332     def _rewrite_membership_op(self, node, left, right):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs)
    319         method = 'visit_' + node.__class__.__name__
    320         visitor = getattr(self, method)
--> 321         return visitor(node, **kwargs)
    322 
    323     def visit_Module(self, node, **kwargs):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit_Compare(self, node, **kwargs)
    654             op = self.translate_In(ops[0])
    655             binop = ast.BinOp(op=op, left=node.left, right=comps[0])
--> 656             return self.visit(binop)
    657 
    658         # recursive case: we have a chained comparison, a CMP b CMP c, etc.

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs)
    319         method = 'visit_' + node.__class__.__name__
    320         visitor = getattr(self, method)
--> 321         return visitor(node, **kwargs)
    322 
    323     def visit_Module(self, node, **kwargs):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit_BinOp(self, node, **kwargs)
    423 
    424     def visit_BinOp(self, node, **kwargs):
--> 425         op, op_class, left, right = self._maybe_transform_eq_ne(node)
    426         left, right = self._maybe_downcast_constants(left, right)
    427         return self._maybe_evaluate_binop(op, op_class, left, right)

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in _maybe_transform_eq_ne(self, node, left, right)
    360     def _maybe_transform_eq_ne(self, node, left=None, right=None):
    361         if left is None:
--> 362             left = self.visit(node.left, side='left')
    363         if right is None:
    364             right = self.visit(node.right, side='right')

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit(self, node, **kwargs)
    319         method = 'visit_' + node.__class__.__name__
    320         visitor = getattr(self, method)
--> 321         return visitor(node, **kwargs)
    322 
    323     def visit_Module(self, node, **kwargs):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\expr.py in visit_Name(self, node, **kwargs)
    437 
    438     def visit_Name(self, node, **kwargs):
--> 439         return self.term_type(node.id, self.env, **kwargs)
    440 
    441     def visit_NameConstant(self, node, **kwargs):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\ops.py in __init__(self, name, env, side, encoding)
     56         self.is_local = (tname.startswith(_LOCAL_TAG) or
     57                          tname in _DEFAULT_GLOBALS)
---> 58         self._value = self._resolve_name()
     59         self.encoding = encoding
     60 

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\ops.py in _resolve_name(self)
     73 
     74     def _resolve_name(self):
---> 75         res = self.env.resolve(self.local_name, is_local=self.is_local)
     76         self.update(res)
     77 

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\computation\scope.py in resolve(self, key, is_local)
    192                 return self.temps[key]
    193             except KeyError:
--> 194                 raise compu.ops.UndefinedVariableError(key, is_local)
    195 
    196     def swapkey(self, old_key, new_key, new_value=None):

UndefinedVariableError: name 'k' is not defined

該当のソースコード

def filter_df(src_df, dict_row, lst_col):

    # 列のフィルタ
    ret_df = src_df[lst_col]
    for k, v in dict_row.items():
        print(ret_df.query('k > @v'))

    return ret_df


df = pd.DataFrame(data = np.arange(21).reshape(7,3), columns=['列1', '列2', '列3'])

df2 = filter_df(df, {'列1':9, '列2':15}, ['列1', '列2'])

試したこと

以下のサイトを確認しつつ、jupyterで試行錯誤してみた。
https://note.nkmk.me/python-pandas-query/

補足情報(FW/ツールのバージョンなど)

python 3.6.6
pandas 0.23.1
numpy 1.14.5

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

        print(ret_df.query('k > @v'))


の箇所は

        print(ret_df.query('{} > @v'.format(k)))


ではないでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/10 12:48

    ありがとうございます❗format等で変数を文字列にして扱わないといけないんですね。

    キャンセル

+1

ret_dfの列名は「列1」「列2」「列3」ですが、このqueryの書き方ではkという名前の列を参照しようとしているからエラーなのでしょう。kが''の中に入っているのがおかしいと思われます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/09 01:06

    ご回答ありがとうございます。
    kが''の中にあるとおかしいということは、
    print(ret_df.query(k' > @v'))のように記載する、ということでしょうか。
    実行するとinvalid syntaxになります。
    (また、pandas公式のqueryのページを見てもそのような起債になっていないように思います。)

    キャンセル

  • 2019/04/09 01:51

    そこが文字列であるべきということは理解できているでしょうか? 文字列を連結する式をちゃんと書かなければだめです。あるいはmagichanさんの回答にあるようにformatを使ってもいいです。

    キャンセル

  • 2019/04/10 12:46

    すみません。理解できました。そういうことなんですね。。ありがとうございます。

    キャンセル

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

  • ただいまの回答率 88.78%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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