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

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

ただいまの
回答率

90.32%

  • Python 3.x

    7435questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • pandas

    677questions

    Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

データフレームの中の一個前の列を参照して、次の列の演算を行う  Python,Pandas

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,096

pepasuke623

score 34

前提

いつもお世話になっております。またまたデータフレームの操作方法について質問させていただきます。

下のようなデータフレームがあるとします。

   humi  temp  year
0    98    23  2010
1    89    30  2011
2    85    22  2012
3    97    25  2013
4    84    24  2014
5    85    31  2015
6    88    22  2016
  • humiはその年の湿度の代表値
  • tempはその年の気温の代表値
  • yearは年度
    を表しているとします。

実現したいこと

質問用に無理やり作ったので少し変な問題設定ですが、

  1. humi(湿度)が90を超える年はhansode(半袖)が流行る
  2. temp(気温)が25を超える年はTanktop(タンクトップ)が流行る
  3. humi(湿度)が90以下、かつtemp(気温)が25以下の年は、前の年の流行が継続される(humi(湿度)が90を超える,かつtemp(気温)が25を超える年は無いものとする)

というルールに従い、データフレームに'clothes'の列を追加して、上記の結果を書き込みます。
出力結果としては次のようになるはずです。

   humi  temp  year  clothes
0    98    23  2010  hansode
1    89    30  2011  Tanktop
2    85    22  2012  Tanktop
3    97    25  2013  hansode
4    84    24  2014  hansode
5    85    31  2015  Tanktop
6    88    22  2016  Tanktop

試したこと

applyとかmapなどを使ってなんとか出来ないものかと試みましたが、「前の年の流行が継続される」という部分が出来ませんでした。
Forループを使って無理やり書けばこんな感じです。

import pandas as pd

# データフレームの定義
df = pd.DataFrame(
    {'year': [2010, 2011, 2012, 2013, 2014, 2015, 2016],
     'humi': [98, 89, 85, 97, 84, 85, 88],
     'temp': [23, 30, 22, 25, 24, 31, 22]})

# 空のデータフレームを作る
df_e = pd.DataFrame(index=range(len(df)), columns=['clothes'])

# Forループで判定
for i in range(len(df)):
    if  df.ix[i,'humi'] > 90:
        df_e.ix[i,'clothes'] = 'hansode'
    elif i > 0 and df.ix[i,'temp'] > 25:
        df_e.ix[i,'clothes'] = 'Tanktop'
    else:
        df_e.ix[i,'clothes'] = 1

# 無理やりくっつける
df = pd.concat([df,df_e],axis=1)

 # 「1」を置き換える
for i in range(len(df)):
    if  i > 0 and df.ix[i,'clothes'] == 1:
        df.ix[i,'clothes'] = df.ix[i-1,'clothes']

print(df)                  


別に好んでForループを使っているわけではなく、なるべく短く簡潔に、かつ高速に動くものを作りたいと思っています。
うまい方法があれば教えていただければと思います。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

0

applyではその行だけで判定可能な値('hansode' or 'Tanktop')を設定し、
その他の場合は None を設定しておきます。
その結果に対して、fillnaの method 引数に'ffill'を指定すると、
Noneを直前の有効値で置き換えることができます。

df['clothes'] = df.apply(lambda s: 'hansode' if s.humi > 90 else 'Tanktop' if s.temp > 25 else None, axis=1).fillna(method='ffill')

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

それぞれの判別する処理を関数にしてapplyしてみました。
前年のデータがなかった場合等の例外処理はしておりませんので、適宜修正してください。

# 半袖かタンクトップを返す
def get_clothes(humi, temp):
    if humi > 90:
        return 'hansode'
    if temp > 25:
        return 'Tanktop'


# 前年のclothe列を返す
def get_prev_clothes(year):
    return df.loc[df['year'] == year - 1, 'clothes'].values[0]


df['clothes'] = df.apply(lambda x: get_clothes(x['humi'], x['temp']), axis=1)

# 上記で判定できなかったデータを処理
prev_clothes = df.loc[df['clothes'].isnull(), 'year'].map(get_prev_clothes)
df.loc[prev_clothes.index, 'clothes'] = prev_clothes

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • Python 3.x

    7435questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • pandas

    677questions

    Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。