🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Anaconda

Anacondaは、Python本体とPythonで利用されるライブラリを一括でインストールできるパッケージです。環境構築が容易になるため、Python開発者間ではよく利用されており、商用目的としても利用できます。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Python

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

pandas

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

Q&A

解決済

2回答

2054閲覧

[Python] pandasを用いてcsvファイルから行を複数条件で抽出したい。

Touiro

総合スコア9

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Anaconda

Anacondaは、Python本体とPythonで利用されるライブラリを一括でインストールできるパッケージです。環境構築が容易になるため、Python開発者間ではよく利用されており、商用目的としても利用できます。

データベース

データベースとは、データの集合体を指します。また、そのデータの集合体の共用を可能にするシステムの意味を含めます

Python

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

pandas

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

0グッド

0クリップ

投稿2020/01/06 13:58

前提・実現したいこと

はじめまして、質問文に不足があるかもしれませんがご容赦ください。
仮に下のようなcsvファイルがあるとき

番号名前年齢国籍性別書類
001新井20日本女性A
001新井20日本女性B
002ジム25米国男性A
003ジム25米国男性B
00419中国女性A
004エレナ19豪州女性A
005エレナ19豪州女性B
006新井25日本男性A
007新井25日本男性B

[名前][年齢][国籍][性別]が同じペアを抽出し、その後[書類]A,Bで[番号]が同じものを取り除きたい、つまり下の表のようにしたいのです。

番号名前年齢国籍性別書類
002ジム25米国男性A
003ジム25米国男性B
004エレナ19豪州女性A
005エレナ19豪州女性B
006新井25日本男性A
007新井25日本男性B

[補足] 本当に最終的にやりたいことは、[書類Aフォルダ]に入っているファイル名(番号と連動)を、書類Bの番号でリネームすることです。
この場合で言えば、ジムの情報が記録された[002.doc]を[003.doc]に自動でリネームすることをファイル全体に行うこと最終目標です。……可能ですよね?

試したこと

ひとまずpython(3.7.4 Anaconda 3)で下のように入力しました。

Python

1# pandasをインポート 2import pandas as pd 3# CSVファイルを読み込む 4df = pd.read_csv('C:/Users/username/Desktop/PythonProject/A and B.csv', encoding='shift_jis') 5# 重複行を出力 6Data1 = (df[df.duplicated(subset=['名前', '年齢', '国籍', '性別'], keep=False)]) 7print(Data1)

これでひとまず

番号名前年齢国籍性別書類
001新井20日本女性A
001新井20日本女性B
002ジム25米国男性A
003ジム25米国男性B
004エレナ19豪州女性A
005エレナ19豪州女性B
006新井25日本男性A
007新井25日本男性B

にできました。しかし、ここから番号の重複、上の表で言えば新井(女性)を除くことが出来ません。

python

1Data4 = (df[df.duplicated(subset=['名前', '年齢', '国籍', '性別'], keep=False)]) ~ (df[df.drop_duplicates(subset=['番号'])]) 2print(Data4)

ではSyntaxErrorを起こしてしまいます。簡単な問題なのかもしれませんが、ご教授ください。宜しくおねがいします。

なお、先に番号の被りを取り除くのは不可でおねがいします。上の表に例示はしませんでしたが、例えば

番号名前
002ジム
003ジム
003エレナ
004エレナ

のような場合、先に番号の被りを取り除いてしまうとジムとエレナが消えてしまいます。個人特定が先でないと(多分)だめなんです。

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

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

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

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

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

meg_

2020/01/06 15:50

subsetに「番号」を追加するのでは駄目なんですか?
Touiro

2020/01/06 16:28

ありがとうございます。 subsetに[番号]を追加する、つまり (df[df.duplicated(subset=['名前', '年齢', '国籍', '性別', '番号'], keep=False)]) ということでしょうか? これですと、番号が一致しているものが出力されてしまう、つまり例示した表で言えば 001 新井 のみが出力されてしまうと認識しています。
guest

回答2

0

ベストアンサー

現状と全く違うアプローチですが、

本当に最終的にやりたいことは、[書類Aフォルダ]に入っているファイル名(番号と連動)を、書類Bの番号でリネームすることです。

というのであれば DataFrame.pivot_table()を使用して

名前年齢国籍性別(番号,A)(番号,B)
エレナ19豪州女性004005
ジム25米国男性002003
新井20日本女性001001
新井25日本男性006007
19中国女性004NaN

のようなデータフレームに変換し、

  • (番号,A)列がNaN ではない
  • (番号,B)列がNaN ではない
  • (番号,A)列の値と(番号,B)列の値が等しくない

という条件を元にフィルタリングし

名前年齢国籍性別(番号,A)(番号,B)
エレナ19豪州女性004005
ジム25米国男性002003
新井25日本男性006007

のようなデータフレームを導くというのはどうでしょうか。

これであれば、ループなどで表から行毎にデータを取得してリネーム処理をすることが容易になります。

以下は動作サンプル

Python

1import pandas as pd 2import io 3 4csv = """ 5番号,名前,年齢,国籍,性別,書類 6001,新井,20,日本,女性,A 7001,新井,20,日本,女性,B 8002,ジム,25,米国,男性,A 9003,ジム,25,米国,男性,B 10004,王,19,中国,女性,A 11004,エレナ,19,豪州,女性,A 12005,エレナ,19,豪州,女性,B 13006,新井,25,日本,男性,A 14007,新井,25,日本,男性,B 15""" 16# データ読み込み処理 17df = pd.read_csv(io.StringIO(csv), dtype={'番号':str}) 18 19# データ変換処理 20df = df.pivot_table(index=['名前','年齢','国籍','性別'], columns='書類', values=['番号'], aggfunc=lambda d:d.values).reset_index() 21# 名前 年齢 国籍 性別 番号 22#書類 A B 23#0 エレナ 19 豪州 女性 004 005 24#1 ジム 25 米国 男性 002 003 25#2 新井 20 日本 女性 001 001 26#3 新井 25 日本 男性 006 007 27#4 王 19 中国 女性 004 NaN 28 29# フィルタリング処理 30df = df[df[('番号','A')].notna() & df[('番号','B')].notna() & (df[('番号','A')]!=df[('番号','B')])] 31# 名前 年齢 国籍 性別 番号 32#書類 A B 33#0 エレナ 19 豪州 女性 004 005 34#1 ジム 25 米国 男性 002 003 35#3 新井 25 日本 男性 006 007

投稿2020/01/07 00:04

magichan

総合スコア15898

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

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

Touiro

2020/01/07 09:44

ありがとうございます、最終目標に向けて大変参考になります。ただ、自分ではサンプルの通りに試したつもりなのですが aise KeyError(i) KeyError: '番号' となってしまいます。 try: と except KeyError: でデータ変換処理をスキップした場合、フィルタリング処理のほうで(?) KeyError: ('番号', 'A') が発生してしまいます。 csv = 'C:/Users/username/Desktop/PythonProject/A and B.csv' としているのがまずいのでしょうか? 日本語のエンコードが出来ていないとか…… 度々申し訳ないですが、宜しくおねがいします。
magichan

2020/01/07 10:08

自分のデータ(csvファイル)で実行してみるとエラーになるということでしょうか。 あと、エラーになるのは pivot_table() の行でしょうかね? とりあえず KeyError: '番号' と出ているのであれば、元のデータフレームから '番号'列が見つからないのでしょう。 考えられることは 「データフレームの読み込みで失敗している」 「'番号'列がIndexになっている」 「カラム名の前後に余分なスペースがついている」 あたりですね。 とりあえずデータフレームを読み込んだ段階で #データフレームが問題なく読み込まれているか確認 print(df) #データサイズに問題ないか確認 print(df.shape) #カラム名に問題が無いか確認(特にスペースが含まれてないか) print(df.columns) などを実行して確認してみてください
Touiro

2020/01/07 11:16 編集

はい、自分のデータだとうまくいきませんでした。 csv = 'C:/Users/username/Desktop/PythonProject/A and B.csv' と指定した上でご指摘の方法を試した所 Empty DataFrame Columns: [C:/絶対/パス] Index: [] (0, 1) Index(['C:/絶対/パス, dtype='object') となっていましたので、そもそもcsvファイルを読み込めていなかったようです(多分……)。パスそのものは他のコードだと機能するので間違っていないと思います。 どうにもこうにもわからないので、当てずっぽうで csv = pd.read_csv('C:/Users/fight/Desktop/Inbox/005 PythonProject/A and B.csv', encoding='shift_jis') と試してみましたが、やはり駄目なようです。 TypeError: initial_value must be str or None, not DataFrame csvを読み込むにはどのようにすれば良いのでしょうか?
magichan

2020/01/07 11:54

なんとなく理由がわかったきがする もしかして csv = 'C:/Users/username/Desktop/PythonProject/A and B.csv' df = pd.read_csv(io.StringIO(csv), dtype={'番号':str}) とかやってませんか? Io.StringIO() は文字列をファイルのように扱うためのAPIなので、本当のファイルを読み込む場合は通常通り df = pd.read_csv('C:/Users/username/Desktop/PythonProject/A and B.csv', dtype={'番号':str}) となります
Touiro

2020/01/07 14:48

完全におっしゃるとおりです。お恥ずかしい。 通りでいくら検索しても参考になりそうなものを見つけられなかったわけです。 おかげさまでうまくいきました。 ひとまず例示していただいたコードのそれぞれの意味を確認していきたいと思います。 ありがとうございました。
guest

0

python

1print(df) 2""" 3 番号 名前 年齢 国籍 性別 書類 40 1 新井 20 日本 女性 A 51 1 新井 20 日本 女性 B 62 2 ジム 25 米国 男性 A 73 3 ジム 25 米国 男性 B 84 4 王 19 中国 女性 A 95 4 エレナ 19 豪州 女性 A 106 5 エレナ 19 豪州 女性 B 117 6 新井 25 日本 男性 A 128 7 新井 25 日本 男性 B 13""" 14 15df = df[df.duplicated(subset=['名前','年齢','国籍','性別'], keep=False)] 16print(df) 17""" 18 番号 名前 年齢 国籍 性別 書類 190 1 新井 20 日本 女性 A 201 1 新井 20 日本 女性 B 212 2 ジム 25 米国 男性 A 223 3 ジム 25 米国 男性 B 235 4 エレナ 19 豪州 女性 A 246 5 エレナ 19 豪州 女性 B 257 6 新井 25 日本 男性 A 268 7 新井 25 日本 男性 B 27""" 28df = df[~(df.duplicated(subset=['番号','名前','年齢','国籍','性別'], keep=False))] 29print(df) 30""" 31 番号 名前 年齢 国籍 性別 書類 322 2 ジム 25 米国 男性 A 333 3 ジム 25 米国 男性 B 345 4 エレナ 19 豪州 女性 A 356 5 エレナ 19 豪州 女性 B 367 6 新井 25 日本 男性 A 378 7 新井 25 日本 男性 B 38""" 39

投稿2020/01/06 16:52

meg_

総合スコア10736

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

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

Touiro

2020/01/07 07:08 編集

なるほど、おっしゃっていた意味が理解できたかもしれません。 たしかに2回目でシンプルに全項目一致を除外すれば良かったということでしょうか。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問