statsmodels.formula.api.ols の formula で AssertionError: になる場合

Jupyter Notebook でポチポチ入力しながら読んでる続き。

a-sue.hatenablog.com

前回のはその後 anaconda の updateを何度か繰り返してたらコンプリートした。

a-sue.hatenablog.com

C:\WINDOWS\system32>conda update --prefix "C:\Program Files\Anaconda3" anaconda
Collecting package metadata: done
Solving environment: done

# All requested packages already installed.


C:\WINDOWS\system32>

ここからが本題。

第12章で statsmodels.formula.api を使うのだけど、謎のエラーが出る。

model = smf.ols(formula='tip ~ total_bill', data=tips)
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-6-a9177a705d62> in <module>()
----> 1 model = smf.ols(formula='tip ~ total_bill', data=tips)

C:\Program Files\Anaconda3\lib\site-packages\statsmodels\base\model.py in from_formula(cls, formula, data, subset, *args, **kwargs)
    145         (endog, exog), missing_idx = handle_formula_data(data, None, formula,
    146                                                          depth=eval_env,
--> 147                                                          missing=missing)
    148         kwargs.update({'missing_idx': missing_idx,
    149                        'missing': missing})

C:\Program Files\Anaconda3\lib\site-packages\statsmodels\formula\formulatools.py in handle_formula_data(Y, X, formula, depth, missing)
     63         if data_util._is_using_pandas(Y, None):
     64             result = dmatrices(formula, Y, depth, return_type='dataframe',
---> 65                                NA_action=na_action)
     66         else:
     67             result = dmatrices(formula, Y, depth, return_type='dataframe',

C:\Program Files\Anaconda3\lib\site-packages\patsy\highlevel.py in dmatrices(formula_like, data, eval_env, NA_action, return_type)
    308     eval_env = EvalEnvironment.capture(eval_env, reference=1)
    309     (lhs, rhs) = _do_highlevel_design(formula_like, data, eval_env,
--> 310                                       NA_action, return_type)
    311     if lhs.shape[1] == 0:
    312         raise PatsyError("model is missing required outcome variables")

C:\Program Files\Anaconda3\lib\site-packages\patsy\highlevel.py in _do_highlevel_design(formula_like, data, eval_env, NA_action, return_type)
    163         return iter([data])
    164     design_infos = _try_incr_builders(formula_like, data_iter_maker, eval_env,
--> 165                                       NA_action)
    166     if design_infos is not None:
    167         return build_design_matrices(design_infos, data,

C:\Program Files\Anaconda3\lib\site-packages\patsy\highlevel.py in _try_incr_builders(formula_like, data_iter_maker, eval_env, NA_action)
     60                 "ascii-only, or else upgrade to Python 3.")
     61     if isinstance(formula_like, str):
---> 62         formula_like = ModelDesc.from_formula(formula_like)
     63         # fallthrough
     64     if isinstance(formula_like, ModelDesc):

C:\Program Files\Anaconda3\lib\site-packages\patsy\desc.py in from_formula(cls, tree_or_string)
    162             tree = tree_or_string
    163         else:
--> 164             tree = parse_formula(tree_or_string)
    165         value = Evaluator().eval(tree, require_evalexpr=False)
    166         assert isinstance(value, cls)

C:\Program Files\Anaconda3\lib\site-packages\patsy\parse_formula.py in parse_formula(code, extra_operators)
    146     tree = infix_parse(_tokenize_formula(code, operator_strings),
    147                        operators,
--> 148                        _atomic_token_types)
    149     if not isinstance(tree, ParseNode) or tree.type != "~":
    150         tree = ParseNode("~", None, [tree], tree.origin)

C:\Program Files\Anaconda3\lib\site-packages\patsy\infix_parser.py in infix_parse(tokens, operators, atomic_types, trace)
    208 
    209     want_noun = True
--> 210     for token in token_source:
    211         if c.trace:
    212             print("Reading next token (want_noun=%r)" % (want_noun,))

C:\Program Files\Anaconda3\lib\site-packages\patsy\parse_formula.py in _tokenize_formula(code, operator_strings)
     92         else:
     93             it.push_back((pytype, token_string, origin))
---> 94             yield _read_python_expr(it, end_tokens)
     95 
     96 def test__tokenize_formula():

C:\Program Files\Anaconda3\lib\site-packages\patsy\parse_formula.py in _read_python_expr(it, end_tokens)
     42     origins = []
     43     bracket_level = 0
---> 44     for pytype, token_string, origin in it:
     45         assert bracket_level >= 0
     46         if bracket_level == 0 and token_string in end_tokens:

C:\Program Files\Anaconda3\lib\site-packages\patsy\util.py in next(self)
    319         else:
    320             # May raise StopIteration
--> 321             return six.advance_iterator(self._it)
    322     __next__ = next
    323 

C:\Program Files\Anaconda3\lib\site-packages\patsy\tokens.py in python_tokenize(code)
     33                 break
     34             origin = Origin(code, start, end)
---> 35             assert pytype not in (tokenize.NL, tokenize.NEWLINE)
     36             if pytype == tokenize.ERRORTOKEN:
     37                 raise PatsyError("error tokenizing input "

AssertionError: 

最初に疑ったのチルダ
自分が入力してる画面に表示されるのと、テキストのが一致しないし、ウェブでは "~" が "?" になってたりするのがよくあるから。
そのへんのキーワードでググってみても見つからない。

最後の何も語らない AssertionError: がいやらしいなぁと思って

statsmodels python ols formula AssertionError

でググってみたらヒットしたのがここ

github.com

Python のバージョンは違うけど、出てるスタックトレースが全く同じ。

これか!ってことでチェックすると

import patsy
patsy.__version__
'0.4.1'

ビンゴ?

おなじみの手順で

C:\WINDOWS\system32>conda update --prefix "C:\Program Files\Anaconda3" patsy
Collecting package metadata: done
Solving environment: done

## Package Plan ##

  environment location: C:\Program Files\Anaconda3

  added / updated specs:
    - patsy


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    patsy-0.5.1                |           py36_0         380 KB
    ------------------------------------------------------------
                                           Total:         380 KB

The following packages will be UPDATED:

  patsy                       pkgs/free::patsy-0.4.1-py36_0 --> pkgs/main::patsy-0.5.1-py36_0


Proceed ([y]/n)? y


Downloading and Extracting Packages
patsy-0.5.1          | 380 KB    | ############################################################################ | 100%
Preparing transaction: done
Verifying transaction: done
Executing transaction: done

C:\WINDOWS\system32>

よし、これで行けた。

と思ったがリロードしても変わらない。

import importlib
importlib.reload(patsy)
patsy.__version__
'0.4.1'

こいつも更新したが変わらない。

C:\WINDOWS\system32>conda update --prefix "C:\Program Files\Anaconda3" statsmodels
Collecting package metadata: done
Solving environment: done

## Package Plan ##

  environment location: C:\Program Files\Anaconda3

  added / updated specs:
    - statsmodels


The following packages will be UPDATED:

  statsmodels        pkgs/free::statsmodels-0.6.1-np111py3~ --> pkgs/main::statsmodels-0.9.0-py36h452e1ab_0


Proceed ([y]/n)? y

Preparing transaction: done
Verifying transaction: done
Executing transaction: done

C:\WINDOWS\system32>

ってか、上の方でやって anaconda が取り込んでるモジュールはすべてアップグレードされてたんじゃないの?

結局 Jupyter を再起動したら更新されたモジュールが読み込まれました。

import patsy
patsy.__version__
'0.5.1'

問題の文でもエラーが出なくなってめでたしめでたし。

model = smf.ols(formula='tip ~ total_bill', data=tips)