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

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

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

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

PyCharm

エディター・開発ツール

Q&A

解決済

2回答

4843閲覧

[Python]csvで一部のデータをカウントアップして更新したい

kei-kappa564

総合スコア19

Python 3.x

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

PyCharm

エディター・開発ツール

0グッド

1クリップ

投稿2018/10/11 05:05

編集2018/10/11 05:07

前提・実現したいこと

コードを実行するとおすすめのレストラン名を聞かれます。
おすすめのレストラン名の質問に対しての回答はrestaurant.csvにて、
"Name"キーと"Count"キーにて保存されます。
"Name"キーには質問の回答のレストラン名が入り、
"Count"キーには質問に対しての回答で何回そのレストラン名が出てきたかをカウントします。

発生している問題・エラーメッセージ

初めて名前が出てきたレストランはしっかりとcsvに記録がされるのですが、
二回目以降名前が出てきたレストラン名に関しては上手く"Count"キーがカウントアップされません、
何故でしょうか。

該当のソースコード

Python

1import csv 2import os 3 4 5print("#####################################################") 6print("どこのレストランが好きですか?") 7print("#####################################################") 8restaurant = input() 9 10# csvファイルが無かったら作成+書き加える→else、在ったら書き加える→if。 11if os.path.exists("restaurant.csv"): 12 with open("restaurant.csv", "r+", newline='') as res_csv: 13 fieldnames = ["Name", "Count"] 14 writer = csv.DictWriter(res_csv, fieldnames=fieldnames) 15 # addはレストランの名前があるか否かのトリガー 16 restaurant_is_exist = False 17 # res_csvをfor文でListにできるように変換 18 new_csv = csv.reader(res_csv) 19 for row in new_csv: 20 print(row) # ここのrowはlist型 21 if (restaurant in row) == True: 22 print(int(row[1]) + 1) 23 row[1] = int(row[1]) + 1 24 print("Restaurant is Exist") 25 restaurant_is_exist = True 26 if restaurant_is_exist == False: 27 writer.writerow({"Name": restaurant, "Count": 1}) 28 print("Restaurant is not Exist") 29 print("If") 30else: 31 with open("restaurant.csv", "w", newline='') as res_csv: 32 fieldnames = ["Name", "Count"] 33 writer = csv.DictWriter(res_csv, fieldnames=fieldnames) 34 writer.writeheader() 35 writer.writerow({"Name": restaurant, "Count": 1}) 36 print("Else")

試したこと

コード中の、

Python

1print(int(row[1]) + 1)

で、実際にカウントアップ出来るのかを確認したりしてみたのですが、
カウントアップは出来ているようでした、しかしそれがrestaurant.csvには反映されていないようです。

補足情報

restaurant.csvの中身です(画像添付出来なかったのでリンクで失礼します)、
これは二回動作させて一回目をhoge、二回目をhogehogeにした結果です。
画像

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

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

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

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

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

guest

回答2

0

初めて名前が出てきたレストランはしっかりとcsvに記録がされるのですが、

二回目以降名前が出てきたレストラン名に関しては上手く"Count"キーがカウントアップされません、
何故でしょうか。

Python

if (restaurant in row) == True:
print(int(row[1]) + 1)
row[1] = int(row[1]) + 1
print("Restaurant is Exist")
restaurant_is_exist = True

変数rowはあくまでもcsvから読み取った結果であって、
書き換えれば自動的にcsvファイルが更新されるわけではありません。

手動で当該行を書き直してやる必要があります。


プログラム冒頭でcsvファイルを全て読み込み、
データを更新した後、プログラム終了直前に再度書き出すのが楽なように思います。

この場合ファイルが既に存在するかに依って書き出しモードを変える必要もありません。

投稿2018/10/11 05:12

編集2018/10/11 05:14
LouiS0616

総合スコア35658

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

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

kei-kappa564

2018/10/11 05:32 編集

回答を頂きありがとうございます。 データベース上でやっているわけでは無いので、 csv上に上書きしなければならなく出来なかったとは私の勉強不足でした。 重ね重ね質問になってしまい申し訳ないのですが2つほどお聞きしたいことがあります。 ①手動で当該行を書き直しすにはどの様な方法があるのでしょうか。appendなどを用いれば出来るのでしょうか。 ➁「プログラム冒頭でcsvファイルを全て読み込み、 データを更新した後、プログラム終了直前に再度書き出すのが楽なように思います。」 とは、csvを全て読み込んだ後、レストラン名を追加 or カウントアップを行ってから全文csvに上書きということでしょうか。 お手数をおかけしますが、 お暇な時で良いのでよろしくお願いいたします。
LouiS0616

2018/10/11 05:32

①開いているファイルをそのまま編集する方法もありますが、大抵コードが難解になるので完全に作り直す方が楽です。 ②概ね、はい。上書きというか同名ファイルの作り直しですね。
guest

0

ベストアンサー

カウントアップされないのは、前回までの結果を読み込んでいないのが原因のため、以下のようにしてみてはどうでしょうか。

サンプルコード

python

1import csv 2import os 3 4data = {} 5 6# ファイルが存在すれば、読み込む。 7if os.path.exists('data.csv'): 8 with open('data.csv', encoding='utf-8') as f: 9 data = {name: int(count) for name, count in list(csv.reader(f))} 10 11print('#####################################################') 12print('どこのレストランが好きですか?') 13print('#####################################################') 14name = input() 15 16# 存在する場合はカウントアップ、そうでない場合はキー追加 17if name in data: 18 data[name] += 1 19else: 20 data[name] = 1 21 22# ファイルに書き込む。 23with open('data.csv', 'w', encoding='utf-8') as f: 24 writer = csv.writer(f) 25 for name, count in data.items(): 26 writer.writerow([name, count])

実行例

csv

1ロイヤルホスト,2 2マクドナルド,1 3ジョナサン,2

入力

##################################################### どこのレストランが好きですか? ##################################################### はなまるうどん

csv

1はなまるうどん,1 2ロイヤルホスト,2 3マクドナルド,1 4ジョナサン,2

追記

python

1# list(reader) は [row for row in reader] と同じ 2lst = list(reader) 3print(lst) 4# [['はなまるうどん', '1'], ['ロイヤルホスト', '3'], ['マクドナルド', '1'], ['ジョナサン', '2']]

python

1for name, count in lst: 2 print(name, count) 3# はなまるうどん 1 4# ロイヤルホスト 3 5# マクドナルド 1 6# ジョナサン 2

lst を dict の内包表現 を使って dict にしています。

python

1dic = {i: i * 2 for i in range(5)} 2print(dic) # {0: 0, 1: 2, 2: 4, 3: 6, 4: 8}

投稿2018/10/11 05:32

編集2018/10/11 06:41
tiitoi

総合スコア21956

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

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

kei-kappa564

2018/10/11 06:26 編集

とても分かりやすい問題解決に繋がるコードを丁寧に書いていただきありがとうございます。 重ね重ね質問になってしまい申し訳ないのですがPython初心者でして一つ質問があります、 data = {name: int(count) for name, count in list(csv.reader(f))} ここの部分は何をしているのでしょうか。 dict形式で作っていると思ったのですが...。
tiitoi

2018/10/11 06:42

dict の内包記法になります。 [['はなまるうどん', '1'], ['ロイヤルホスト', '3'], ['マクドナルド', '1'], ['ジョナサン', '2']] というリストを {'はなまるうどん': 1, 'ロイヤルホスト': 3, 'マクドナルド': 1, 'ジョナサン': 2} にしています。 追記したので、参考にしてください。
kei-kappa564

2018/10/11 07:14

詳しく追記して頂きありがとうございます。 どの様に動いているのかある程度理解できるようになりました。 三度失礼なのですが、1つ問題が発生しまして、 先ほどの教えて頂いたコードを1回目実行するのは問題なく動いたのですが、 2回目の実行の時に以下の様なエラーが出てしまいました。 Traceback (most recent call last): File "C:/Users/〇〇〇/PycharmProjects/python_programming/practice01-kai.py", line 9, in <module> data = {name: int(count) for name, count in list(csv.reader(f))} File "C:/Users/〇〇〇/PycharmProjects/python_programming/practice01-kai.py", line 9, in <dictcomp> data = {name: int(count) for name, count in list(csv.reader(f))} ValueError: not enough values to unpack (expected 2, got 0) ※〇は伏字 これは値が足りていないエラーなのは理解できましたが、 どの様に解決すればよろしいのでしょうか。
tiitoi

2018/10/11 07:27

csv の各列は `レストラン名,数` となっていることを想定しています。 編集されたりして空行が入ってしまったのかもしれません。 ``` data = {row[0]: int(row[1]) for row in list(csv.reader(f)) if row} ``` に書き換えてみてはどうでしょうか。if row で row が空文字の場合は無視するようにします。
kei-kappa564

2018/10/11 07:39

書き換えたら出来ました、ありがとうございます。 他にも下記の一行に、 ``` with open('data.csv', 'w', encoding='utf-8') as f: ``` newline=''を付け加えても改行が取り払われて出来ました。 ``` with open('data.csv', 'w', encoding='utf-8', newline='') as f: ``` 色々とお手数をおかけしまして申し訳ありません、 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問