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

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

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

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

4回答

1342閲覧

1, 2, 12ではなく'12'でフラグを立てたい

Pablito

総合スコア71

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/08/21 00:23

編集2019/08/21 01:47

前提・実現したいこと

現在、アンケートベースのデータをクレンジングしています。
そこで好きな商品を聞く質問で、
数字ごとにマスターから商品を当てはめていきたいのですが、
二桁の数字、例えば12の時に1, 2, 12の三つに数字を認識してしまい、
3つの数字全てでフラグが立ってしまいます。
これを12だけでフラグ立てしたいです。

該当のソースコード

Python

1def shampoo13 (row): 2 if '12' in row: 3 return 1 4 else: 5 return 0 6 7data['shampoo13'] = data['a4'].apply(shampoo13)

data['a4']は

0 12 1 2 2 1 3 4 4 0;1;2;3;4;5;6;7;8;9;10;11;12;13;14 ... 123878 7 123879 12 123880 12 123881 14 123882 7 Name: a4, Length: 1123883, dtype: object

となっており、
現状の結果は、
最初の列(12が回答として得られている)で

1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 _1 1_ 0 0 0 0 0 0 0 0 0 0 0 0

のようになっていて、理想の結果は

1 2 3 4 5 6 7 8 9 10 11 12 13 14 0 0_ 0_ 0 0 0 0 0 0 0 0 0 0 0 0

です。
宜しくお願い致します。

quiquiさんにご指摘頂いた 1 2 のコードは

Python

1def shampoo2(row): 2 if '1' in row: 3 return 1 4 else: 5 return 0 6 7data['shampoo2'] = data['a4'].apply(shampoo2) 8 9def shampoo3(row): 10 if '2' in row: 11 return 1 12 else: 13 return 0 14 15data['shampoo3'] = data['a4'].apply(shampoo3)

です。
###試してみたこと
"%02d" %を入れてみて、

Python

1def shampoo13 (row): 2 if '"%02d" %12' in row: 3 return 1 4 else: 5 return 0 6 7data['その他市販'] = data['a4'].apply(shampoo13)

のようにもしてみましたが、
逆に12にフラグが立たなくなってしまいました。。。

何卒お力添え宜しくお願い致します。

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

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

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

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

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

can110

2019/08/21 01:19

data['a4']の中身、現状の結果、理想の結果を提示ください。
hellomartha

2019/08/21 01:27

記載されているコードで shampoo13('1') やshampoo13('2')は0が返ってくると思いますが、何が問題ですか? 実際には if '1' in row elif '2' in row ・・・と続くコードを書いてるのでしょうか?
Pablito

2019/08/21 01:28

can110さん 質問を加筆修正致しました。 宜しくお願い致します。
Pablito

2019/08/21 01:29

hellomarthaさん それが1と2も12の中に含まれると判断してしまい、 1が返ってきてしまいます。 それが問題なのです。
quickquip

2019/08/21 01:34

def shampoo2 (row): □if '1' in row: □□return 1 □else: □□return 0 data['shampoo2'] = data['a4'].apply(shampoo2) みたいなコードが引用していないところにあるのではないですか?(□はインデントです)
Pablito

2019/08/21 01:40

quiquiさん コメントありがとうございます。 それは原因がということですか???
quickquip

2019/08/21 01:44

12の時に12だけに立って欲しいのに1, 2, 12に立って困ると言うことですが、考えてみてください。 「12に立っている」という状況は「正しい」のですよね? 「正しくない」のは「1が立っている」と「2が立っている」という状況の方ですよね? であれば質問に提示するべきなのは「1を立てる処理」と「2を立てる処理」の方ではありませんか?
Pablito

2019/08/21 01:46

quiquiさん なるほど すぐ加筆修正します。
can110

2019/08/21 01:46

現状の結果と理想の結果の見方がよく分かりません。 上段「1 2 3 ~」と下段「0 _1 1_~」は何を表しているのでしょうか? 単純に「print(data['shampoo13'])」の、現状と理想の結果を提示されたほうが分かりやすいかと思います。
guest

回答4

0

数字でフラグをたてたいのなら

# -*- coding: utf-8 -* def shampoo13 (row): if row == 12 : return 1 else: return 0 row = 12 print(shampoo13(row)) コード

ではないでしょうか?

文字列と数字を混同してませんか?

投稿2019/08/21 01:15

nanami12

総合スコア1015

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

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

Pablito

2019/08/21 01:19

ご回答ありがとうございます。 こちらはobjectととして読み込んだ12などの数字が、 設問の回答に含まれかどうかで判定するものとなっています。 理由はこの設問は複数回答なので、 実際に1, 2, 3, 12などの場合があるため、 ==としてしまうとこのような 回答がカウントされなくなってしまうことです。 そのうえでアドレスがありましたら、 何卒宜しくお願い致します。
nanami12

2019/08/21 01:27

can110さんも書かれている通り、data['a4']の中身、を記載し 実行すると結果hogehogeをxxx という結果にしたいと言うような 具体例を記載しなければ、解決策を導けないとおもいます。
Pablito

2019/08/21 01:31

質問を変更しました! ご確認よろしくお願い致します。
nanami12

2019/08/21 02:14

if hoge in hogehoge の構文は 文字列やリストに対して判定するものです。 ですから、先にも述べましたが、文字列と数字を混同してませんか? と記載しました。数値として比較するには hellomarthaさんの御指摘のように テーブル設計を見直した方がよろしいかとおもいます。 数値として、比較したいのであれば == で 判定出来るように
guest

0

ベストアンサー

選択されている項目を得たいだけであれば、if文を使うまでもなくこれで良いと思うのですが。

Python

1import pandas as pd 2df = pd.DataFrame({'a4': ['12','2','1','4','0;1;2;3;4;5;6;7;8;9;10;11;12;13;14']}) 3 4a4_df = df['a4'].apply(lambda d: pd.Series(map(int, d.split(';'))).value_counts()).fillna(0).astype('int') 5print(a4_df) 6# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 7#0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 8#1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 9#2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 10#3 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 11#4 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

投稿2019/08/21 02:45

編集2019/08/21 02:47
magichan

総合スコア15898

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

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

Pablito

2019/08/21 02:57

ご回答ありがとうございます。 書いて実行してみたのですが、 なんか重くて完了できません。。。
magichan

2019/08/21 04:14

確認しました。ダミーで123882行のデータを生成して実行してみたところ、私の環境では処理に88秒かかりました・・・確かに重いですね。 とりあえず、 value_counts() を value_counts(sort=False) とソート処理を無効にするパラメータを与えてみたところ、48秒と半分くらいになりました。 まだ重いのですが、とりあえずこれで試してみてください。
magichan

2019/08/21 04:59

DataFrame.apply() であれば dict を返しても、DataFrameを生成できるので a4_df = df.apply(lambda d: {int(k):1 for k in d['a4'].split(';')}, axis=1, result_type='expand').fillna(0).astype('int') と書けますね。 これだと私の環境で14秒程度です。
Pablito

2019/08/21 05:15

様々ありがとうございます。 今業務の関係で別の部分をやらないといけないのですが、 終わり次第試したいと思います。 取り急ぎですが、宜しくお願い致します。
Pablito

2019/08/21 08:32

すいません。 実行したのですが、 MemoryError: Unable to allocate array with shape (1123676, 15) and data type float64 が起きてしまいました。。。
magichan

2019/08/21 23:50

メモリー不足ですか・・・ 今回はもっと軽い方法の方が良さそうですね
Pablito

2019/08/22 08:40

そうですね。。。 試行錯誤してみます。
Pablito

2019/08/26 06:40 編集

すいません。 いったん軽いデータにしたらできました! ありがとうございます!
guest

0

質問内容がうまく把握できてませんが、ようは以下のような結果を得たいということでしょうか。

Python

1import pandas as pd 2 3def shampoo(num, v): 4 l = map(int, v.split(';')) # 数値リストに変換 5 if num in l: 6 return 1 7 else: 8 return 0 9 10data = pd.DataFrame({'a4':['12','2','1','4','0;1;2;3;4;5;6;7;8;9;10;11;12;13;14']}) 11for num in [1,2,12]: # とりあえず3列分 12 data['shampoo{}'.format(num+1)] = data['a4'].apply(lambda v: shampoo(num, v)) 13print(data) 14""" 15 a4 shampoo2 shampoo3 shampoo13 160 12 0 0 1 171 2 0 1 0 182 1 1 0 0 193 4 0 0 0 204 0;1;2;3;4;5;6;7;8;9;10;11;12;13;14 1 1 1 21"""

投稿2019/08/21 02:13

can110

総合スコア38266

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

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

Pablito

2019/08/21 08:35

回答ありがとうございます。 試してみたのですが、 MemoryError: Unable to allocate array with shape (1123883,) and data type uint64 が返ってきてしまいました。。。 少し負荷がかかりすぎなようなので、 また明日挑戦してみたいと思います。
guest

0

数値を無理やり文字列比較で場合分けしているのが問題だと思います。
dataの回答部分(文字列)を数値配列に変換するところから進めることをお勧めします。

0 12 1 2 2 1 3 4 4 0;1;2;3;4;5;6;7;8;9;10;11;12;13;14 ↓ answer[0] = [12] answer[1] = [2] answer[2] = [1] answer[4] = [0,1,2, ・・・・・13,14]

とりあえず質問にある最初の問題(12を入れたら1,2,12にフラグがたつ)の原因は

shampoo2("12") = 1 #文字列"12"に'1'が入っているから shampoo3("12") = 1 #文字列"12"に'2'が入っているから

これを回避するためにはnanami12さんの回答にあるように、
関数に数値を渡すようにして==で数値比較をします。


質問の内容とはずれますが補足として。
回答データのなかに、1が含まれるか、2が含まれるか・・・・14が含まれるかと
それぞれの判定で関数を作るのは良くない設計です(シャンプーの種類が増えたらその分だけ関数追加する必要がでてくるので)
1つの関数としてまとめたほうが良いと思います。

投稿2019/08/21 01:45

編集2019/08/21 02:52
hellomartha

総合スコア329

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

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

Pablito

2019/08/21 02:05

回答ありがとうございます。 a4をint型にして試しましたが、 結果は一緒でした。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問