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

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

ただいまの
回答率

90.51%

  • Python 3.x

    6450questions

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

  • pandas

    586questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,630

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

  • 解決済

    n行ごとに新しい列にデータを移す(Pandas/Python)

    Pandas(Python)で1列にまとめられたデータをn行ごとに新しい列に移すにはどうすればよいのでしょうか。 具体的には、a1列にある数値を4行ごとに新しい列に移すということを

  • 解決済

    Dataframeでのif文について

    前提・実現したいこと pythonのpandasでdataframeを作り、表の中で条件に当てはまる行にフラグを立てたいと思っています for文とif文でかんたんに実現できるかなと

  • 解決済

    python3 dataframeの複数行の一括挿入について

    タイトルの件について、pythonのdataframeの複数行の一括挿入についての質問です。 下記のような事を行っているのですが、dataframeを挿入する関数(insert_d

  • 解決済

    連続する日付の差分の計算

    前提・実現したいこと 下記の左端のような、dateのログが入ったデータフレームを、日付の連続性で区別したいですが方法がわかりません。 カラム("difference")を1列追

  • 解決済

    pythonのDataframeで一行ごとに繰り返し処理をさせたい

    前提・実現したいこと python初心者です。 close>20ma列がSからL,LからSに変わった場合にclose列の値を返して、そうでない場合はposition列の直前の文字を

  • 解決済

    Pyhton pandas で重複行のカウント

    【やりたい事】 csvファイル中の5万行×4列のデータの中で重複する行の個数をカウントしようとしています。 【背景】 Excelのピボットを組もうとすると、動作を停止するので、

  • 解決済

    データフレームの要素のうち、大文字のみで書かれた部分のみ取り出したいです

     前提・実現したいこと python pandas データフレームの要素のうち、大文字で書かれた部分のみ取り出したいです。以下のデータフレームdf1において、Person1~Per

  • 解決済

    python 要素内のソートについて

    下記にてtimeカラムの要素ごとにソートをかけたいのですが やり方がわからずご教授頂きたいです。  ID   time        0    [6, 4]   

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

  • Python 3.x

    6450questions

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

  • pandas

    586questions

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