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

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

ただいまの
回答率

90.52%

  • Python 3.x

    6388questions

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

  • pandas

    584questions

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

padas dataframe 複数条件の入れ子について

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 189

MitMc

score 17

dataframeの扱いで、複数条件の抽出が上手くいきません。
開催日のみで絞り込んでから、それを新しいデータフレーム に入れて、その後、レース数で絞り込むという方法以外の方法があれば教えてください。(新しいデータフレームを作らない形でお願いします。)

対象のデータフレーム 

開催日    レース
0    2017-01-28    1
0    2017-01-28    2
0    2017-01-28    3
0    2017-01-28    4
0    2017-01-28    5
0    2017-01-28    6
0    2017-01-28    7
0    2017-01-28    8
0    2017-01-28    9
0    2017-01-28    10
0    2017-01-28    11
0    2017-01-28    12
0    2017-01-29    1
0    2017-01-29    2
0    2017-01-29    3
0    2017-01-29    4
0    2017-01-29    5
0    2017-01-29    6
0    2017-01-29    7
0    2017-01-29    8
0    2017-01-29    9
0    2017-01-29    10
0    2017-01-29    11
0    2017-01-29    12
0    2017-01-30    1
0    2017-01-30    2
0    2017-01-30    3
0    2017-01-30    4
0    2017-01-30    5
0    2017-01-30    6
0    2017-01-30    7
0    2017-01-30    8
0    2017-01-30    9
0    2017-01-30    10
0    2017-01-30    11
0    2017-01-30    12

実現したいこと
上記のようなデータフレームにおいて、2017-01-28の5(レース)から2017-01-30の3(レース)までの行を抽出したい。

試したコード

df[[(df["開催日"]>="2017-01-28") &(df["レース"]>=2)]&[(df["開催日"]<="2017-01-30") & (df["レース"]<=5)]]


エラー

TypeError                                 Traceback (most recent call last)
<ipython-input-27-bc9d3402f15f> in <module>()
----> 1 new_df[[(day>="2017-01-28") &(race>=2)]&[(day<="2017-01-30") & (race<=5)]]
      2 #&new_df[(day<="2017-01-30") & (race<=5)]

TypeError: unsupported operand type(s) for &: 'list' and 'list'
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+1

「実現したいこと」に書いてある条件はどう見ても矛盾しているので無視して、2017-01-28第2レースから2017-01-29第5レースまでを選択するコードを書いてみました。

df1[
  (df1.apply(lambda x: "{} {:02}".format(x["開催日"], x["レース"]), axis=1)>="2017-01-28 02") &
  (df1.apply(lambda x: "{} {:02}".format(x["開催日"], x["レース"]), axis=1)<="2017-01-29 05")
]

追記: datetime型をサポートしうまくいったコード全体を示します。

#!/usr/bin/env python3
import pandas as pd
import io

df1 = pd.read_table(io.StringIO("""
開催日    レース
0    2017-01-28    1
0    2017-01-28    2
0    2017-01-28    3
0    2017-01-28    4
0    2017-01-28    5
0    2017-01-28    6
0    2017-01-28    7
0    2017-01-28    8
0    2017-01-28    9
0    2017-01-28    10
0    2017-01-28    11
0    2017-01-28    12
0    2017-01-29    1
0    2017-01-29    2
0    2017-01-29    3
0    2017-01-29    4
0    2017-01-29    5
0    2017-01-29    6
0    2017-01-29    7
0    2017-01-29    8
0    2017-01-29    9
0    2017-01-29    10
0    2017-01-29    11
0    2017-01-29    12
0    2017-01-30    1
0    2017-01-30    2
0    2017-01-30    3
0    2017-01-30    4
0    2017-01-30    5
0    2017-01-30    6
0    2017-01-30    7
0    2017-01-30    8
0    2017-01-30    9
0    2017-01-30    10
0    2017-01-30    11
0    2017-01-30    12
"""), delim_whitespace=True
)
df1["開催日"] = pd.to_datetime(df1["開催日"])

df2 = df1[
  (df1.apply(lambda x: "{} {:02}".format(x["開催日"], x["レース"]), axis=1)>="2017-01-28 00:00:00 02") &
  (df1.apply(lambda x: "{} {:02}".format(x["開催日"], x["レース"]), axis=1)<="2017-01-29 00:00:00 05")
]
print(df2)

```

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

まず最初に。

"開催日"列にて、日時データでの比較演算を行うのであれば、"開催日"列のデータは文字列(Object型)として扱うのではなく、datetime型 で扱いましょう。

その上で条件に会う行の検出は以下のように記述できます。

import datetime as dt
res = df[((dt.datetime(2017,1,28) == df["開催日"]) & (df["レース"] >= 2)) |
         ((dt.datetime(2017,1,29) == df["開催日"]) & (df["レース"] <= 5))]

"レース"列が datetime型 なのであれば単に日付だけの比較で

res = df[((df["開催日"].dt.day == 28) & (df["レース"] >= 2)) |
         ((df["開催日"].dt.day == 29) & (df["レース"] <= 5))]

でも良いかもしれません。

以下、動作サンプル

import datetime as dt
import pandas as pd

df = pd.DataFrame({
    "開催日" : ['2017-01-28'] * 12 + ['2017-01-29'] * 12 + ['2017-01-30'] * 12,
    "レース" : [1,2,3,4,5,6,7,8,9,10,11,12] * 3
    })
print(df)

df["開催日"] = pd.to_datetime(df["開催日"])

res = df[((dt.datetime(2017,1,28) == df["開催日"]) & (df["レース"] >= 2)) |
         ((dt.datetime(2017,1,29) == df["開催日"]) & (df["レース"] <= 5))]
print(res)
#    レース        開催日
#1     2 2017-01-28
#2     3 2017-01-28
#3     4 2017-01-28
#4     5 2017-01-28
#5     6 2017-01-28
#6     7 2017-01-28
#7     8 2017-01-28
#8     9 2017-01-28
#9    10 2017-01-28
#10   11 2017-01-28
#11   12 2017-01-28
#12    1 2017-01-29
#13    2 2017-01-29
#14    3 2017-01-29
#15    4 2017-01-29
#16    5 2017-01-29

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/07/10 19:29

    ご回答ありがとうございます。

    申し訳ないのですが、質問を変更させていただきました。
    1月28日と1月29日であれば、いただいたコードの通りなのですが、この期間が1月28日〜30日となった場合(実際はもっと長期の期間を想定しているのですが、teratailへの質問上、短い期間としてます)、
    日が連続していないので、==で指定してしまうと29日が抜けてしまいます。
    しかし>=、<=で指定すると、求めている以上の日付が選択されてしまいます。この場合、どうしたら良いでしょうか?

    キャンセル

  • 2018/07/10 20:55

    単純に日付("開催日"列)だけの絞込み、例えば、 『1/10 から 1/29 までの全レース』などの場合

    df[(dt.datetime(2017,1,10) <= df["開催日"]) &
    (dt.datetime(2017,1,29) >= df["開催日"])]

    のように不等号を使っても全く問題ないと思います。

    問題は"レース"列を含んで『1/10の4レース から 1/29の5レースまで』などの場合ですね・・
    その場合は条件文を並べて

    df[((dt.datetime(2017,1,10) == df["開催日"]) & (df["レース"] >= 4)) |
    ((dt.datetime(2017,1,11) <= df["開催日"]) & (dt.datetime(2017,1,28) >= df["開催日"])) |
    ((dt.datetime(2017,1,29) == df["開催日"]) & (df["レース"] <= 5))]

    のように書くとよいのではないでしょうか

    キャンセル

  • 2018/07/10 21:31

    MitMcさん
    まさにそういう状況を考慮して私は「日付とレース番号を纏めたもの」をまず作って大小比較を試みるコードを書きました。
    中日を考慮して複雑なand式を立てるよりシンプルだと思います。 試してみて頂きたい。

    キャンセル

  • 2018/07/11 07:23

    magichan様
    再度、教えていただき、ありがとうございます。
    参考にいたします。

    キャンセル

  • 2018/07/11 07:28

    KojiDoi様

    頂いたコードを試したのですが、dataframeが空になり、上手くいきませんでした。
    前提としてお話しすべきだったのですが、開催日は文字列ではなく、datetimeになっております。そのせいで上手くいかなかったのでしょうか?
    再度、string型に直してみてから試そうと思うのですが、なかなか上手くいかず.... df["開催日"].string()では駄目でしょうか。

    キャンセル

0

start_df = new_df[(day=="2017-01-28") &(race>=2)]
end_df = new_df[(day=="2017-01-30") &(race<=5)]
middle_df =  new_df[(day>"2017-01-28") &(day<"2017-01-30") ]

pd.concat([start_df, middle_df,end_df ])

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

  • 解決済

    日付からフラグを付ける

    以下のようなdata内の開始月・終了月のデータから月ごとに継続フラグを付けたいです。 開始月          0 201602 1 201602  2 201601

  • 解決済

    pythonのスライスについて

    a = b[:,0] このようなコードがあったとき、どのようなことがおこなわれますか? bはこのコードがなりたつ何かだとすると なにだったら成り立ちますか? すみません、間

  • 解決済

    python dataframe 結合で全組み合わせ

    python のデータフレームの結合で、2つのデータフレームの全組み合わせを取得したく、以下のような処理で行ってみました。 一応目的の全組み合わせは取得できたのですが、ダミーの

  • 解決済

    pandas DateTimeIndex型の時刻のみ指定したデータ抽出について

    下記のようなpandasのDateTimeIndex型のインデックスとなっているデータ:dataで、時刻のみ指定してデータを抽出方法があれば、ご教授頂きたいです。 説明不足でしたの

  • 解決済

    pythonのsheet別の出力方法

    pythonで例えば、 a=np.arange(30).reshape(10,3) b=np.arange(20).reshape(5,4) という行列を作り、“np.savetx

  • 解決済

    pythonでの変数やハッシュの扱いに関する質問です

    実現したいこと python でデータ処理をしています. for文内でpandasのデータフレームの抽出をして, それらを逐次異なる変数に入れたいのですが,いまいち変数の保存(定義

  • 解決済

    辞書を小さいもの順にソートしたい

    辞書を小さいもの順にソートしたい。 df変数に {"A": [{"a": 100}, {"b": 200}, {"c": 300}], "B": [{"a": 400}, {"

  • 解決済

    毎日のデータに隔日のデータを結合する

    現在の商品販売データの解析を行っています。 以下の2つのデータを所持しています。 日付(YYYY/MM/dd) 月 商品コード 売上 2017/01/01 1

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

  • Python 3.x

    6388questions

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

  • pandas

    584questions

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