パソコン仕事5倍塾
35,000人を指導した東大卒・元日本IBM社内講師が直伝
MENU
藤本 博子さんの投稿
(投稿ID: 5362)
import csv import random from datetime import datetime,timedelta ''' 「1」サンプルデータの作成 先頭列 :日時データ 1000マイクロ秒毎に加算(年・月・日 時間:分:秒.000000マイクロ秒) 行見出 :アイテムa アイテムb アイテムc ・・・ 行データ:ランダムの数値 float_a,float_b,float_c 「2」辞書の形式で保存 {key(先頭列日時データ):{item_a:float_a,item_b:float_b,item_c:float_c} 2022-03-01 10:00:00.001000:{'a': 0.18047978517289842, 'b': 0.8172327998831116, 'c': 0.2295418854425827} ''' dic = {} categories = ["a","b","c"]#見出し行 item名 dt = datetime(2022,3,1,10,0,0)#日付生成データ開始時間 for c in range(0,50):#50行データを生成 dt = dt + timedelta(microseconds=1000)#日付は1000マイクロ秒毎に加算 # dt_str = dt.strftime("%Y-%m-%d %H:%M:%S.%f") dic_num = {} for n,ls in enumerate(categories): num = random.random() #{a:num1,b:num2,c:nmu3}の要素を作成する辞書 dic_num.update({ls:num}) # print(dic_num) # 辞書(キー)date:要素{a:num1,b:num2,c:nmu3} の辞書を作成する dic[dt] = dic_num ''' 「3」「2」の辞書データを、csvに書き出すためのリストオブジェクトを作成する。 辞書のアイテムをコピーして、新しい辞書に保存→その辞書に、key(先頭列日時データ)の要素も一緒にリスト化する。 date_type_list {'a': 0.18047978517289842, 'b': 0.8172327998831116, 'c': 0.2295418854425827, 'date': '2022-03-01 10:00:00.001000'} ''' date_type_list = [] for key,value in dic.items(): new_dic = value.copy() new_dic["date"] = key date_type_list.append(new_dic) ''' 「4」「3」のリストのデータを、csv.Dictwriterでcsvファイルに書き出す。 見出行の順序は、date,item_a,item_b,item_cの順番に書き出す。→小川先生のリライトをみて、すごい!と思った。 ''' with open("test_data_microsecond.csv",newline="",mode="w",encoding="utf-8") as f: field_names = ("date","a","b","c") writer = csv.DictWriter(f,fieldnames=field_names) writer.writeheader() writer.writerows(date_type_list)
''' 「5」指定された開始時刻・終了時刻に該当した部分のみ、参照元csvから書出先のEXCLに転記する。 書き込みする対象 start_time = "2022-03-01 10:00:00.015000" 以降 end_time = "2022-03-01 10:00:00.031000" より前のデータ ''' import csv import openpyxl ''' csvのデータを辞書形式で読み込み、リストを作成する [{'date': '2022-03-01 10:00:00.001000', 'item_a': , 'b': '0.2922968193072939', 'c': '0.9474747444571356'}… ] ''' date_type_list = [] with open("test_data_microsecond.csv",mode="r",encoding="utf-8") as f: for row in csv.DictReader(f): date_type_list.append(row) ''' エクセルへ書き出す為の辞書を作成する {key(先頭列日時データ):{item_a:float_a,item_b:float_b,item_c:float_c} ''' dic = {} for val in date_type_list: key = val["date"] tmp_dic = {} for k,v in val.items(): if k != "date": tmp_dic[k] = v print(tmp_dic) dic[key] = tmp_dic for k,v in dic.items(): print(k,v,sep="☆") ''' エクセルへ書き出す時間を変数に格納する ''' start_time = "2022-03-01 10:00:00.015000" end_time = "2022-03-01 10:00:00.031000" ''' エクセルへ書き出す時間を変数に格納する 作業したエクセルファイル用のPath変数をつくる エクセルの所定フォーマットの見出行の順序は、a,c,b (参照元csvの見出し行は、a,b,c) ''' wb = openpyxl.load_workbook("test_data_microsecond.xlsx") wb_mod = "test_data_microsecond_mod.xlsx" sh = wb["data"] items_list = [] #転記先の見出行のリスト for row in sh.iter_rows(min_row=1,min_col=2,max_row=1,max_col=4): for r in row: items_list.append(r.value) print(items_list) ''' csvデータから読み取ったデータから、指定した開始時間・終了時間の間のデータをエクセルファイルに書出す。 書出し先の項目の順序は、読み取りデータとは違うため、一致した項目の列に書出する。最後に編集用エクセルファイルに保存する。 ''' cnt = 2 #key:date v:itemsとdataのvalue for d,val in dic.items(): if start_time < d < end_time:#日付データが開始時間・終了時間の間 sh.cell(row=cnt,column=1).value = d print(val) for k,v in val.items(): for c, i in enumerate(items_list): if k == i:#辞書のkey (項目名 a,b,c) と、転記先エクセルの項目名(a,c,b)が一致したら、float型のデータを書出す sh.cell(row=cnt,column=c+2).value = v cnt += 1 wb.save(wb_mod)
''' テキストファイルへ書出し テキストファイルへ書出す場合、文字列への変換が必要。 書出し内容が日付データ、数値の場合は、CSVファイルへ書き出した方がよいと思う。 ''' import random from datetime import datetime,timedelta from pathlib import Path import csv dic = {} categories = ["a","b","c"] dt = datetime(2022,3,1,10,0,0) # 日時・項目・数値のデータを作成 for c in range(0,50): dt = dt + timedelta(microseconds=1000) dt_str = dt.strftime("%Y-%m-%d %H:%M:%S.%f") dic_num = {}#初期化 for n,ls in enumerate(categories): num = random.random() #{a:num1,b:num2,c:nmu3}の要素を作成する辞書 dic_num.update({ls:num}) # 辞書(キー)date:要素{a:num1,b:num2,c:nmu3} の辞書を作成する dic[dt_str] = dic_num date_list = [] for key,val in dic.items(): tmp_list = [] for k,v in val.items(): tmp_list.append(str(v)) tmp_list.insert(0,key) date_list.append(tmp_list) ''' pythonで作成したデータをtextファイルへ書出し .joinメソッドで改行する ''' #text書出し用の見出し行のリスト midashi = categories.copy() print(id(midashi),id(categories)) midashi.insert(0,"date") mod_path = Path("./output.txt") with mod_path.open(mode="w",encoding="utf-8") as f: f.write("\t".join(midashi)+"\n")#見出し行 for row in date_list: r = map(str,row)#文字列で結合のため、map関数 row_data = "\t".join(r) f.write(row_data+"\n") ''' 書出したtextファイルを読み込んで、print関数で出力してみる ''' read_path = Path("./output.txt") with read_path.open(encoding="utf-8") as f: read_row = f.read() print(read_row) print(type(read_row))# class "str" w_path = Path("./output_2.txt") with mod_path.open(mode="w",encoding="utf-8") as f: f.write("\t".join(midashi)+"\n")#見出し行 for row in date_list: r = map(str,row)#文字列で結合のため、map関数 row_data = "\t".join(r) f.write(row_data+"\n")
田中 宏明さんのコメント
(コメントID: 7717)
小川 慶一さんのコメント
(コメントID: 7718)
藤本 博子さんのコメント
(コメントID: 7722)
Captcha:
たった1ヶ月で人生が劇的に変わりました
佐藤信さん
役員クラスの方から高い評価を受けるようになりました。
佐賀県 - 岩本徹さん
今までまったく知らなかったショートカットキーを使いまくっています。
東京都 - 鷹觜慶さん
年齢60才間近、営業で外回りの時間が多い私でも退社時間が1-2時間程度早くなりました。
東京都 - 宗内隆明さん
受講前もすでにパソコン得意でしたが、そんな私でも受講して本当に良かったと思えた講座です。
東京都 - 佐伯とも子さん
ここまで包括的に仕事に役立つ深い学びを受けれた講座は初めてでした
東京都 - 飯田倫子さん
2025年03月12日 00:12
2025年02月26日 08:51
2025年02月25日 00:11
2025年02月13日 08:06
2025年02月10日 09:35
2025年03月12日 22:46
2025年03月12日 07:41
2025年02月26日 16:39
2025年02月26日 16:36
2022年02月24日 10:59
表示できる投稿はありません。
この学習サイトの教材制作、サポート、システム開発をすべてやっています。
2022年02月02日 00:00
2022年02月02日 03:00
2022年02月02日 06:00
2022年02月02日 09:00
2022年02月02日 12:00
2025年02月28日 09:44
2024年12月19日 11:30
2024年12月18日 13:30
2024年10月21日 17:30
2024年10月18日 17:00
2025年02月04日 08:51
2025年02月03日 12:58
2024年11月27日 11:48
2024年11月25日 12:07
2024年11月17日 09:51
2025年03月13日 00:17
2025年02月26日 23:24
2025年02月25日 23:32
2025年02月24日 22:07
2025年02月21日 22:39
2025年02月26日 16:37
2025年02月24日 15:44
2025年02月24日 15:42
2025年02月15日 15:10
2025年02月11日 04:54
2025年03月04日 22:18
2025年03月02日 14:34
2025年02月27日 22:25
2025年02月26日 00:04
2025年02月24日 23:16
2025年03月08日 07:15
2025年03月04日 15:36
2025年02月26日 16:38
2025年02月24日 22:57
藤本 博子さんの投稿
(投稿ID: 5362)
■結論
・pythonで日付データを生成し、CSVへ書き込み、保存したファイルを開いた場合
生成した日付データの表示形式が秒単位以下の細かい単位になると、見た目が誤変換のように見えました。
日付データをmicroseconds単位で書き込みしたCSVを開くと、00:00.0 という表示形式になりました。
しかし、pythonで生成した日付データは、正しい内容でCSVに保存されており、CSV→Excelにpntyonで生成した日付データの内容で書き出せることを確認しました。
(ISO8601形式? yyyy-mm-dd hh:mm:ss.SSSSSS (例)2022-03-01 10:00:00.016000)
・textファイルでpythonのmicroseconds単位の日付データを書き込んだ場合、表示形式はpythonで生成した書式形式と同じでした。(事前に文字列に変換しないとtextに書き込みできませんが)
結果は問題なかったので、自分的には、慌てずに対処しようと思いました。という、どうしようもないオチです…
実際に自分で確かめたこと、また小川先生にリライトしてもらったcsv.Dictwriter,Dictreaderや辞書型への変換のバリエーションなど、自分のケースで適用できたことはよかったと思いました。
一応試したこと
・CSVへ書き出すときに、日付データをstrftimeメソッドで文字列に予め変換しても、マイクロ秒の日付データは、CSVでは、00:00.0という書式のままでした。
・また、CSVへ書き込む時に表示形式を指定できるのか方法を探しましたがみつかりませんでした。
■確認した背景
実務で日付データを扱うVBAの相談を受けたことがありました。(日付データは、秒単位、ミリ秒と単位が細かい)
作業内容は、参照元のCSVファイルから、指定された開始日時、終了時間に該当する部分だけ、所定のExcelファイルに書き込む、その際、参照元(csv)と書き込み先(Excel)の行見出しの順序は一致しない)というものです。
pythonでも同じ作業をすることができるか、確認したいと思いました。
■確認したこと:
「1」pythonでCSVに書き込みした場合
timedeltaオブジェクトの引数単位別加算して50行のデータを生成。CSVで日付データがどう表示されるのか確認しました。
timedelta(引数) csv書出(見た目上) データの中身
minutes=1 2022/3/1 10:01 2022/3/1 10:01:00 ・・・分単位であれば、誤変換と間違う混乱は無し
seconds=1 2022/3/1 10:00 2022/3/1 10:00:01 ・・・見た目上、秒単位が表示されない。実際のデータの中身は問題無し
microseconds1=1000 00:00.0 2022/3/1 10:0:0.001 ・・・見た目上、誤変換と見間違う。でも、実際のデータの中身は問題無し(ユーザー定義が必要 yyyy/m/d h:m:s.000)
notepad(txtファイル)から開くと、日付データは正しく表示される。 例:2022-03-01 10:00:00.001000
float型の表示
元データ(小数点17桁)→ 書出先のCSV:小数点15桁まで表示(16桁目切捨)
notepad(txtファイル)から開くと、元データと同じく小数点16桁まで表示される
「2」pythonから書き込んだCSVファイルを読み込み、Excelへ書き込んだ場合
日付データ → 元データと同じマイクロセカンド(6桁表示)2022-03-01 10:00:00.002000
float型 → 小数点16桁まで表示(文字列型になってましたが)
「3」pythonで、textファイルへ書出した場合
・textへ書き込む場合、事前に文字列に変換が必要となります。writeメソッド(文字列) writelines()メソッドもあるようですが・・・
書出し内容が日付データ、数値の場合は、文字列に変換する必要があるので、CSVで書き込みした方がよいと思いました。
・表示される日付データの書式、float型小数点の桁数は、pythonで生成した元データと同じ桁数になりました。
田中 宏明さんのコメント
(コメントID: 7717)
が、過去にVBAでCSVの日付データ(ミリ秒)をExcelに正しく書き出しされたという
話自体がスーパー事務員を物語っていますね。
CSVとは、Comma Separated Valueの略。
Comma(カンマ)でSeparated (区切られた)Value(値)が規則的に配置された
テキストファイルで書式情報を持っていないので、取り扱いに苦労しています。
小川 慶一さんのコメント
(コメントID: 7718)
「結論」を読んだのですが、何が言いたいのか分かりませんでした。
以下がもつれているからではないかと感じます。
それぞれ別物として考えてください。
[a]
PythonからのCSVファイルへの、ミリ秒単位の日付時刻の出力
(テキストファイルでも良いのですが、要はテキスト形式での日付時刻の出力)
[b]
ミリ秒単位の日付時刻を含むCSVファイルの、エクセルでの読み込み
[c]
ミリ秒単位の日付時刻を含むCSVファイルの、エクセル形式への変換
[d]
ミリ秒単位の日付時刻を含むエクセルファイルの、エクセルでの読み込み
[b], [d] は、いったん開いたあとでも、セルの書式設定で「yyyy/mm/dd h:mm:ss.000」や「h:mm:ss.000」を指定すればいけるのではないという気も。
一気にやりたいなら、ファイルを開く→ミリ秒を含む日付時刻を含む列の書式設定を自動で行うマクロを書いてしまえば良いかと。
workbook の open イベントを使えば一気にやれるかも。
[c] については、[b], [d] が解決したならば、[c]では悩む必要はなくなるかと。
上記のとおりに [b], [c], [d] が解決したならば [a] で日付時刻の出力をどうするかということは、「[b]で問題にならないような書式で出力すれば良い」という平易な問題になります。
田中さんもおっしゃっているとおり、CSVファイルは、拡張子こそ .csv ですが、中身は値が comma で区切られた文字列が並ぶテキストファイルです。
なので、 notepad 等のテキストエディタで開くと、テキスト形式で中身を見ることができます。
一方、エクセルで(ファイル読み込みウィザード等を用いずに、単純にダブルクリック等で)開こうとすると、エクセルは、セルの値を元に列ごとの書式を勝手に変更してしまいます。
藤本 博子さんのコメント
(コメントID: 7722)
コメントくださいまして、ありがとうございます。
CSVファイルをダブルクリックし、Excelが起動した時の仕様について理解不足でした。
私の理解不足、考えのもつれを解きつつ、解説くださいましてありがとうございます。
Excelは、セルの値を元に、列ごとの書式を勝手に変更してしまうことを理解しました。
数字のみの値で先頭の0(ゼロ)が消える(ゼロ落ち)の場合の対処法は行っていたのですが、
日付のデータの変換が、自分の想定外の挙動だったので、混乱していまいました。
申し訳ございません。
田中さんの実務上の経験を踏まえたお返事も大変参考になりました。
田中さん
私は、抜け作事務員です…(;^_^A
これからも、色々教えていただけると、とってもうれしいです。
大変参考になりました。ありがとうございます!