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

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

ただいまの
回答率

88.78%

apply関数を使ってdfの要素毎に関数を適用する方法について

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 309

mi2

score 33

やりたいこと

AA1111
BB222CC
DDD250E

このデータから数字とアルファベットの間に区切りを入れて、

<1列目> <2列目> <3列目> <4列目> <5列目> <6列目> <7列目> <8列目> <9列目> <10列目>・・・
AA1111 AA●1111 AA■1111 AA 11・・・
BB222CC BB●222●CC BB●222CC BB222●CC BB■222■CC BB■222CC BB222■CC BB 222 CC BB 222CC BB222 CC・・・
DDD250E DDD●250●E DDD●250E DDD250●E DDD■250■E DDD■250E DDD250■E DDD 250 E DDD 250E DDD250 E・・・

のように、区切りを入れた上で列は不揃いの複数の組合せをdfで取得し出力したいと考えています。

記号の数を増やす際に、defの内容をDataFlameにdf.apply(def, axis=1)の形で適用させて上記を実現しようとしていますが、重複が出てきてしまうことでうまく適用できていない箇所があるように見受けられます。

作成したコード

# ★★
import pandas as pd
import re
import itertools

def func(row):

    default = row[0]
    # 空白
    space = re.sub(r'((?<=\d)\D|(?<=\D)\d)', r' \1', default)
    # スペース区切り
    lst = space.split(' ')
    # ●挿入
    ret = []
    for tpl in itertools.product(['','●'],repeat=len(lst)-1):
        p = lst[0]
        for t,l in zip(tpl,lst[1:]):
            p += t + l
        ret.append(p)
    # 空白(半角スペース)挿入
    for tpl in itertools.product(['',' '],repeat=len(lst)-1):
        p = lst[0]
        for t,l in zip(tpl,lst[1:]):
            p += t + l
        ret.append(p)
    # ■挿入
    for tpl in itertools.product(['','■'],repeat=len(lst)-1):
        p = lst[0]
        for t,l in zip(tpl,lst[1:]):
            p += t + l
        ret.append(p)

    # 重複がある場合削除
    ret = list(set(ret))

    # 列を追加
    for idx,val in enumerate(ret):
        if idx > 0: # 先頭列は不要
            row[idx] = val

    return row

# データ
data = pd.read_csv('test.csv', header=0)
print(data) # ['AA1111','BB222C','DD25EE'])

# 関数を適用する
df = data.apply(func,axis=1)
print(df) # IndexError: ('index 1 is out of bounds for axis 0 with size 1', 'occurred at index 0')

## dfへの適用がうまくいかなかったので、下記を試してみました。

# リスト型
dflist = data.values.tolist()

# 内包表記
res = [ flatten for inner in dflist for flatten in inner ]

# df2
df2 = pd.DataFrame(res)
df2.rename(columns={"model":"0"})

# 関数を適用する
df2 = df2.apply(func,axis=1)
print(df2)

結果

    0    1    2    3    4    5    6    7    8    9
0    AA1111    AA1111    AA 1111    AA■1111    NaN    NaN    NaN    NaN    NaN    NaN
1    BB222CC    BB 222 CC    BB 222CC    BB■222■CC    BB●222CC    BB222 CC    BB222CC    BB●222●CC    BB222■CC    BB222●CC
2    DDD250E    DDD■250■E    DDD250 E    DDD250E    DDD 250 E    DDD■250E    DDD●250E    DDD●250●E    DDD250■E    DDD 250E

考察

一見出来たように見えるのですが、df1行目については'AA●1111'がなく、2行目については'BB★222CC'とDDD250Eがなく、df2行目については'AA■1111'がなく、df3行目については'DDD●250E'がない状況となっています。また、その箇所が重複箇所となっていることがわかりました。

これはどの部分により組合せが崩れて同じものが出てくる状態になっているのでしょうか。
適切に取得するためにはどのようにコードを変更したらよさそうかお教え頂けましたら幸いです。
何卒よろしくお願い申し上げます。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

これはどの部分により組合せが崩れて同じものが出てくる状態になっているのでしょうか。

前回の回答に不具合がありました。失礼しました。
以下、修正後の処理にて書いてみました。なお、IndexErrorは当方環境では発生しませんでした。

import pandas as pd
import re
import itertools

# 指定区切り文字を組み合わせ挿入したリストを返す
# ただし区切文字を含まない要素(「AA1111」など)は含めない
def insert(lst,char):
    ret = []
    for tpl in itertools.product(['',char],repeat=len(lst)-1):
        p = lst[0]
        for t,l in zip(tpl,lst[1:]):
            p += t + l
        ret.append(p)
    return ret[1:] # 区切文字を含まない要素は含めない

def func(row):
    default = row[0]
    # 空白
    space = re.sub(r'((?<=\d)\D|(?<=\D)\d)', r' \1', default)
    # スペース区切り
    lst = space.split(' ')

    ret = []
    ret += insert(lst, '●') # ●挿入
    ret += insert(lst, ' ')  # 空白(半角スペース)挿入
    ret += insert(lst, '■') # ■挿入

    # 列を追加
    for idx,val in enumerate(ret):
        row[idx+1] = val # 区切文字を含まない先頭列は残しておく

    return row

# データ
#data = pd.read_csv('hondaBIKEtest.csv', header=0)
data = pd.DataFrame(['AA1111','BB222C','DD25EE'])

# 関数を適用する
df = data.apply(func,axis=1)
print(df)
"""
        0        1        2         3        4        5         6        7        8         9
0  AA1111  AA●1111  AA 1111   AA■1111      NaN      NaN       NaN      NaN      NaN       NaN
1  BB222C  BB222●C  BB●222C  BB●222●C  BB222 C  BB 222C  BB 222 C  BB222■C  BB■222C  BB■222■C
2  DD25EE  DD25●EE  DD●25EE  DD●25●EE  DD25 EE  DD 25EE  DD 25 EE  DD25■EE  DD■25EE  DD■25■EE
"""

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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