

やりたいことは以下になります。

IDごとに直近1年分の売上データがあり、直近ｎケ月の金額がｎ万円を連続して超える人が何人いるかカウントしたいと考えています。

例えば、直近3ケ月の金額が17万円を連続して超える人数(3ケ月の中で1ケ月でも17万円を下回る月がある人は含まれない)、16万円を連続して超える人数、15万円を超える人数、…1万円を超える人数とスタート地点の金額から1万円刻みで人数をカウントしたいです。

（上記例でいうと17万を連続して超える人は当然16万円を連続して超えることになるので、IDの重複は許すことにします）

for文を使えば簡単にできると思うのですが、どのように記述すれば良いのかわからないのでご教示いただけますと幸いです。

[![画像の説明をここに入力](https://i.stack.imgur.com/5r4d1.png)](https://i.stack.imgur.com/5r4d1.png)


CC BY-SA 4.0
2021-03-28T05:19:22.567
74938
2021-04-05T07:15:24.363
2021-03-28T06:01:36.313
19110
42369
question
python python3
IDごとに直近nか月の金額がｎ万円を連続して超える人数をカウントしたい


その後の追記・更新が無いようですが、以下のような記事が参考になるでしょう。

[Pandas DataFrame select rows based on values of multiple columns whose names
are specified in a list](https://stackoverflow.com/q/54299161/9014308)  
[pandasで欠損値NaNを除外（削除）・置換（穴埋め）・抽出](https://note.nkmk.me/python-pandas-nan-
dropna-fillna/)  
[Pythonのrange関数の使い方](https://note.nkmk.me/python-range-usage/)  
[iloc -
Pandasで要素を抽出する方法(loc,iloc,iat,atの使い方)](https://deepage.net/features/pandas-
location.html#iloc)  
[Pythonの組み込み関数all(), any()の使い方](https://note.nkmk.me/python-all-any-usage/)  
[pandasで行数、列数、全要素数（サイズ）を取得](https://note.nkmk.me/python-pandas-len-shape-
size/)  
[Pythonのf文字列（フォーマット済み文字列リテラル）の使い方](https://note.nkmk.me/python-f-strings/)

* * *

  * 最初の`KINGAKU_S`の列が`ID`
  * 次の列が直近月のデータで、以降xヵ月前が並んでいる
  * `NaN`は`0`円として扱う
  * `xx円を超える`は`xx円`を含む

上記あたりを仮定・補完して考えると、以下のようなプログラムで出来るでしょう。

[code]

    import pandas as pd
    data = pd.read_csv('data.csv') #### CSV読み取り、必要ならheader,encoding等指定、EXCELならread_excel()を使う
    data.fillna(0.0, inplace=True) #### 'NaN' を '0.0' とする
    
    months = 3          #### nヵ月分とするか指定
    startvalue = 170000 #### 処理開始金額
    
    for threshold in range(startvalue, 0, -10000): #### 降順 1万円刻み
        count = len(data[data.iloc[:,1:months+1].apply(lambda x: all([v >= float(threshold) for v in x]), axis=1)]) #### 集計
        print(f'{threshold: >7} : {count: >6}')    #### 表示
    
[/code]


CC BY-SA 4.0
2021-04-05T06:17:55.437
75090
2021-04-05T06:17:55.437
26370
74938
answer


例えばこのようなデータを考えてみます

  * 横に月が並ぶ
  * 縦(行頭)が ID とする

連続した三ヶ月分の最小値を取り出し, 一定値を超えているかどうか  
2月から 4月分までの場合, 4月が該当する月, という判断にします  
(つまり(どのようなデータであっても) 1月, 2月は件数ゼロ)

[code]

    import pandas as pd
    import numpy as np
    
    # とりあえずランダムな値を実験用に用意
    df = pd.DataFrame(np.random.randint(1000, 20000, (4, 12)))
    df.rename(columns=lambda v: f'{v+1}月', index=lambda v: f'ID_{v:03d}', inplace=True)
    display(df)
    
    # (とりあえず) 8000 以上の値の表示, 及び 件数の表示
    b8k = df.rolling(3, axis=1).min() >= 8000
    display(df[b8k].fillna(''))
    b8k.sum()
    
[/code]

| 1月 | 2月 | 3月 | 4月 | 5月 | 6月 | 7月 | 8月 | 9月 | 10月 | 11月 | 12月  
---|---|---|---|---|---|---|---|---|---|---|---|---  
ID_000 | 2261 | 8830 | 14073 | 15578 | 3376 | 4917 | 17502 | 7456 | 15905 |
1747 | 17220 | 3247  
ID_001 | 11592 | 3769 | 4658 | 12233 | 16910 | 8890 | 8288 | 7854 | 10683 |
5842 | 4346 | 7808  
ID_002 | 4803 | 9351 | 1450 | 17890 | 9665 | 19335 | 11165 | 10414 | 14457 |
14395 | 10539 | 13496  
ID_003 | 12803 | 3727 | 7279 | 9647 | 17536 | 4401 | 16852 | 11295 | 14799 |
2446 | 12863 | 1393  
  
| 1月 | 2月 | 3月 | 4月 | 5月 | 6月 | 7月 | 8月 | 9月 | 10月 | 11月 | 12月  
---|---|---|---|---|---|---|---|---|---|---|---|---  
ID_000 |  |  |  | 15578 |  |  |  |  |  |  |  |  
ID_001 |  |  |  |  |  | 8890 | 8288 |  |  |  |  |  
ID_002 |  |  |  |  |  | 19335 | 11165 | 10414 | 14457 | 14395 | 10539 | 13496  
ID_003 |  |  |  |  |  |  |  |  | 14799 |  |  |  
  
1月 0  
2月 0  
3月 0  
4月 1  
5月 0  
6月 2  
7月 2  
8月 1  
9月 2  
10月 1  
11月 1  
12月 1  
dtype: int64


CC BY-SA 4.0
2021-04-05T06:43:55.167
75092
2021-04-05T07:15:24.363
2021-04-05T07:15:24.363
43025
43025
74938
answer