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

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

ただいまの
回答率

88.34%

(Python)複数のtextファイル読込

解決済

回答 5

投稿 編集

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

club33gold

score 1

前提・実現したいこと

初歩的な質問で大変恐縮なのですが、ご教示をお願い致します。

①Pythonで同フォルダ内にある複数のtextファイルを読込み
②一つのtextファイルに結合
③②について、textファイルとして出力をしたいです。

フォルダ名称:Pass
ファイル名:aaa_200701.txt、aaa_200702.txt … aaa_200712.txt

ただしそれぞれに同一のヘッダーがあります。
単純に結合する事は出来たのですが、2ファイル目以降を読み込む際、ヘッダーは読まないようにしたいです。

・aaa_200701.txtのデータ型
日付 商品 担当者 点数 金額
200701 a1  b1  c1 10 10000

・aaa_200702.txtのデータ型
日付 商品 担当者 点数 金額
200702 a1  b1  c1 8 8000


・【ALL】aaa.txt(※最終的に作りたいデータ)
日付 商品 担当者 点数 金額
200701 a1  b1  c1 10 10000
200702 a1  b1  c1 8 8000


この場合、どのようなコードを使用すれば良いでしょうか?

試したこと

■使用したコード

①②について

import glob, codecs

for file in glob.glob("Pass/aaa*.txt"):
file_data = open(file, "r",encoding="utf-8")
print(file_data.read())

file_data.close

→ただし2ファイル目以降のヘッダーも読んでしまうのでNG

③について

file=codecs.open(Pass/【ALL】aaa.txt', 'w'))

解決に向けた仮説

(A案)
・aaa_200701.txtは全て読む
・aaa_200702.txt~2行目以降を読む
・上記を【ALL】aaa.txt'として結合?

(B案)
・aaa_200701.txtの1行目のみ読む
・aaa_200701.txt~2行目以降を読む
・上記を【ALL】aaa.txt'として結合?

(C案)
・aaa_200701.txt~をaaa_200701.CSVに変換して読込?

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • y_shinoda

    2020/07/11 02:18

    「何を質問したいのか」を質問欄に追記おねがいします

    キャンセル

回答 5

checkベストアンサー

+2

B案のほうが良いと思います。

  • 余計な分岐が無いので処理が簡潔
  • ヘッダー行だけに何らかの操作を加えるような拡張に対して柔軟

例えば、こんなふうに。

with open('out.txt', mode='w') as fout:
    files = glob.glob('aaa*.txt')
    assert files

    # ヘッダーの出力
    with open(files[0]) as fin:
        header = next(fin)
        fout.write(header)

    # データ行の出力
    for file in files:
        with open(file) as fin:
            next(fin)   # ヘッダーのスキップ
            fout.writelines(fin)

ヘッダーだけheader.txtから読んでくるとか、
ハードコーディングするとか、そのような変更をしたい場面も多々あるでしょう。

そのようなときもヘッダー行の書き込み処理だけをいじれば良いので簡単です。


本筋から逸れますが、
txtファイルではなくcsvファイルとして扱ったほうが後々扱いやすいかもしれません。

...よく見たら、C案がこれに相当するのですね。
ぶっちゃけ拡張子は半分ただの飾りなので、.txtのままCSV扱いもできます。
試したいことがあるなら気軽にトライできますよ。

もうちょっと複雑な処理が必要になるようであれば、テキストのまま扱うと面倒になってきます。

追記:私の頭の中にあるコード

with open('out.txt', mode='w') as fout:
    files = glob.glob('aaa*.txt')
    assert files

    # ヘッダーの出力
    header = ['日付', '商品CD', '担当CD', '点数', '金額']
    hdr2 = ','.join(header)
    fout.write(hdr2)

    # データ行の出力
    for file in files:
        with open(file) as fin:
            next(fin)   # ヘッダーのスキップ
            fout.writelines(fin)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/19 08:57

    カンマ区切りで出力したいのだと思っていましたが、違いましたか?
    私がイメージしているコードを回答本文に追記してみました。ちょっと試してみて下さい。

    キャンセル

  • 2020/07/20 01:22 編集

    ありがとうございます。
    結論として、” ”・”,”いずれの方法でもインポートとエクスポートが可能になりました。

    --------------------------------------------------------------------------------------------

    ●問題点と解決したい点
    ・エクスポートされたデータをコピーして、エクセルに貼付
    ・1行目:ヘッダーはhdr2 = ','.join(header)を使用するとカンマ区切で結合、A1セルに貼付される
    ・2行目の以降はきちんとA2/B2/C2/D2…に貼付される
    →1行目についてもA1/B1/C1/D1…に貼付したい
     (※ただし読込設定でカンマ区切り等を設定すれば何とか読み込める)

    ●解決出来た点
    ・hdr2 = ”  ”.join(header)を使用
    ・2行目以降の値について、区切りのスペースが長い”  ”だったため、こちらを使用
    ・結果として、エクスポートされたデータをコピーしてエクセルに貼付した際、きちんと表示される
     ようになった。
     (※文字列・数字列の概念は今回は不問)

    キャンセル

  • 2020/07/20 01:23

    多大なご教示を頂きまして、誠にありがとうございました。

    こちらの内容にてベストアンサーとさせて頂きます。

    キャンセル

+1

たんに最初の1行を読み飛ばせばいいだけでは。
難しく考える必要はないと思いますが

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/12 00:27

    初心者のため、勝手が分からずに申し訳ありません。

    単独ファイルで最初の1行を読み飛ばす事は出来るのですが、複数ファイルの場合が分かりませんでした。

    キャンセル

0

この問題を解くだけであれば、どの案でも構いません
難易度も大して変わりません

単一の課題であれば、どれか興味のある方法で問いてみましょう

単一の課題でなく、今後コードを拡張して別の問題を解いたり、何かにコードを利用するのであれば、
出題者に
「今後の拡張や利用も考えると、どの案が良いですか?」
と訊いてから進めた方が、無駄がなくてよいかもしれません

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/12 00:31

    ありがとうございます。
    後学のために(難易度が変わらないのであれば)A~C案を全て知りたいですが、一先ずはB案が良いと思います。

    理由としては、もしヘッダーがない情報が発生した際、こちらで作成したheader.tableなどとマージすれば良いと考えたためです。

    キャンセル

0

p.py

import glob

def read_file(file_name):
    with open(file_name) as f:
        lines = f.read().splitlines()
    return [lines[0], lines[1::]]

out_file = "all.txt"
in_files = "20*.txt"
out_head = None
with open(out_file, "w") as f:
    for file in sorted(glob.glob(in_files)):
        head, rows = read_file(file)
        if out_head == None:
            out_head = head
            f.write(head + "\n")
        if len(rows) > 0:
            f.write("\n".join(rows) + "\n")

実行例
イメージ説明

参考情報:

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2020/07/12 07:17 編集

    A 案です。

    with open(out_file, "r") as f:
    print(f.read())
    とするとよいです。
    上のコメントのコードでは f.close を忘れがあります。 with を使えば close 忘れ防げます。

    キャンセル

  • 2020/07/13 11:32

    ありがとうございます!

    キャンセル

  • 2020/07/13 19:10

    A,B案とも正確には 全部行を読むけど、どうやってヘッダ行を残す・捨てるの制御をするかの方針の差ですね。

    キャンセル

0

回答になってないかもしれませんが、個人的にはB案が一番汎用性があり良いと思います。

コードはそこまで難しくは無いはずです。
わからないことがあれば、質問してくだされば幸いです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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