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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Python 3.x

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

Q&A

解決済

1回答

3629閲覧

DataFrame内の要素が0の時、前の行の値をとってくるコードについて

jun.k

総合スコア28

Python 3.x

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

0グッド

0クリップ

投稿2017/10/03 06:57

以下のデータフレームの各列において、null値ではなく0がランダムに入っている場合に、その0が入っている箇所を同列の前行の値で補完したい場合、どのようなコードが簡潔でしょうか。
replaceとかwhereなどの利用も考えたのですが、null値を補完するfillnaの引数method='ffill'のような機能はなさそうなので、考えあぐねています。

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5037 entries, 0 to 5036
Columns: 156 entries, Date-Time to USWRKW=ECI
dtypes: float64(155), object(1)
memory usage: 6.0+ MB

Indexはdatetime型 columnsは文字列型で要素はfloat型です。

お手数ですがよろしくお願い致します。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

簡潔かどうかわかりませんが…

1.ループにて列毎に処理する

Python

1import pandas as pd 2 3df = pd.DataFrame({'X':[1,2,0,4,5],'Y':[1,0,3,0,5]}) 4for col in df: 5 df[col] = df[col].replace(to_replace=0, method='ffill')

2.0 を一度 np.nan に置き換えて fillna() を使う

Python

1import pandas as pd 2import numpy as np 3 4df = pd.DataFrame({'X':[1,2,0,4,5],'Y':[1,0,3,0,5]}) 5df = df.replace(to_replace=0,value=np.nan).fillna(method='ffill', axis=0)

などはどうでしょうか?


【追加】

3.DataFrame.where() を使う

Python

1import pandas as pd 2 3df = pd.DataFrame({'X':[1,2,0,4,5],'Y':[1,0,3,0,5]}) 4df = df.where(df!=0, df.shift(1))

投稿2017/10/03 08:15

編集2017/10/03 23:15
magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jun.k

2017/10/03 08:33

いつもありがとうございます。非常に簡潔です!! referenceにもreplaceでできる旨載っていましたね・・・。英語苦手でちゃんと見れていませんでした・・・・・
magichan

2017/10/03 23:17

よくよく考えたら df.where() / df.mask() を使う方法もありました。これが一番簡潔かもしれません。
jun.k

2017/10/04 01:30

ご丁寧にありがとうございます。 shiftを使うとカラム内データがすべて縦にずれてしまうではないかと思ったのですが、上記コードを実行するとそうはなりませんね・・・。どういうロジックなのでしょうか。
magichan

2017/10/04 01:40

df.where() は第一引数の条件に合致した部分は保持、条件に合致しない部分を第二引数に置き換える。という関数です。(df.mask() は逆に条件に合致した部分のみ変更) ですので、条件に合致しない 「値が0の部分」のみが shift() の値に置き換わります。
jun.k

2017/10/04 05:36

今までwhere()について勝手に勘違いをしていました。 where(条件,trueの時の値、falseの時の値)で引数は必ず3つ必要だと思っていました。df.where(df!=0,,df.shift(1))のように書かなくても値保持以外の内容だと、自動的にfalseの時の値に置き換えるという理解でよいでしょうか。 またこの場合のshift(1)は列全体をずらすのではなく前行の値を入れるということになるのでしょうか(ここもshitf(-1)ではなくてshift(1)なんですね)。 すみません、もう一つ教えてください。replaceを使う場合に、引数をto_replace<0と不等式を入れると、下記のとおりエラーになるのですが、この場合はreplaceで対応できないのでしょうか。 NameError Traceback (most recent call last) <ipython-input-218-e03b3f4c260d> in <module>() ----> 1 df = df.replace(to_replace<=0,value=np.nan).fillna(method='ffill', axis=0) NameError: name 'to_replace' is not defined
magichan

2017/10/04 06:36

where() に関してですが、たぶん numpy.where() と混同しているかと思います。 pandas.DataFrame.where() と numpy.where() は別物ですのでお気をつけてください。 shift(1) に関してですが、DeataFrame全体を下側に1つシフトさせております。で、値が 0 の場合はそのシフトさせた DataFrame を上書きすることになるので、結果 前行の値が入力されることとなります。
jun.k

2017/10/04 08:26

本当ですね。np.whereではなくdf.whereなんですね。よく分かりました。気をつけます。 shiftもreplaceもよく理解できました。ありがとうございます!!! 非常に勉強になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問