質問するログイン新規登録
Python

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

Q&A

解決済

4回答

358閲覧

ファイルの中の数字を並び替えたい

yyicp

総合スコア87

Python

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

1グッド

0クリップ

投稿2025/08/26 07:40

1

0

実現したいこと

下図のように数字を並び替えて、sample20.txtからsample20mod.txtを作りたいと考えています。

イメージ説明

実行すると、以下の画面が表示されます。blkoldの値は正しいですが、blknewの値は正しくありません。どのように直したら良いでしょうか。

blkold [[5] [0] [0] [8]] blknew [[0] [0] [0] [8]] blkold [[5] [0] [1] [4]] blknew [[0] [1] [0] [4]] blkold [[5] [1] [1] [1]] blknew [[1] [1] [1] [1]]

該当のソースコード

data_filesの中身は今は1つですが、たくさんある状態を想定しています。

python

1import numpy as np 2import pandas as pd 3 4data_files = ['sample20.txt'] 5 6for f in data_files: 7 newname = os.path.splitext(f)[0] + 'mod.txt' 8 g = open(newname,'w') 9 10 for blk in pd.read_csv(f, header=None, chunksize=4): 11 blk = blk.to_numpy() 12 print('blkold') 13 print(blk) 14 blk[0], blk[1], blk[2] = blk[1], blk[2], blk[0] 15 print('') 16 print('blknew') 17 print(blk) 18 print('') 19 20 for i in range(0,4,1): 21 g.write(str(blk[i])+'\n') 22 if i == 3: 23 g.write('\n')

試したこと

14行目が間違っているだろうと思っていますが、どのように直したら良いか分かりませんでした。

melian👍を押しています

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

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

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

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

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

TakaiY

2025/08/26 08:34

メタな質問で恐縮です。 今回の質問のような、特殊な形式のファイルの内容を操作することに関する質問をたくさんされていますが、どのような目的でそのような処理をされているのでしょうか? 仕事でこのようなデータを扱っていて必要だから、とか、pythonの学習が目的、とか、加えてnumpyとかpandasが使えるようになりたい、など。
yyicp

2025/08/26 08:46

>TakaiY様 コメントありがとうございます。 回答は、「仕事でこのようなデータを扱っていて必要だから」です。
guest

回答4

0

コメントしたので、自分なりの回答です。

  • ファイル名の操作はpathlibを使います。
  • この種の処理にnumpyやpandasは使わない。

python

1import pathlib 2 3def read_file(filepath): 4 data = [] 5 record = [] 6 with open(filepath, 'r') as f: 7 for line in f: 8 line = line.strip() 9 if line == '': 10 if record: 11 data.append(record) 12 record = [] 13 else: 14 record.append(line) 15 if record: 16 data.append(record) 17 return data 18 19def write_file(data, output_file): 20 with open(output_file, 'w') as f: 21 for record in data: 22 f.write('\n'.join(record) + '\n\n') 23 24def swap_record(record): 25 return [record[2], record[0], record[1], record[3]] 26 27 28input_file = pathlib.Path('sample20.txt') 29output_file = input_file.with_stem(input_file.stem + 'mod') 30 31data = read_file(input_file) 32data = [swap_record(record) for record in data] 33write_file(data, output_file)
  • 1行を1データ、空行をレコード区切りとして、以下のようなデータ構造で読み込む。
    [['5', '0', '0', '8'], ['5', '0', '1', '4'], ['5', '1', '1', '1']]
  • 読み込み、処理(入れ換え)、書き出しを関数にした
  • 冗長ぎみに書いている
    入れ換えのところはめんどうになって内包表記にしてしまった
  • numpy使っていないので、floatになっちゃうとか気にしなくてすむ。
    こういうことするなら、慣れているなら別だけど、numpy使わないほうがいいと思っている。

今回はちゃんと動かしたので、動くと思います。
意図がわかるコードにしたつもり。

投稿2025/08/26 11:19

TakaiY

総合スコア14600

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

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

yyicp

2025/08/27 00:48

できました。 どうもありがとうございました。
guest

0

既に解決済みなので御参考ですが,質問「ファイルから値を入力し,その値を変更する」の回答 を基にした記述例を下記に示します。

Python

1data_files = ['sample20.txt'] 2 3for fname_before in data_files: 4 with open(fname_before, 'r') as f: 5 lst = [s for s in f.read().splitlines() if s] 6 blks = [lst[i:i + 4] for i in range(0, len(lst), 4)] 7 8 blks = [[c, a, b, d] for a, b, c, d in blks] 9 10 fname_after = fname_before.replace('.txt', 'mod.txt') 11 ss = '\n'.join(''.join(s + '\n' for s in r) for r in blks) 12 with open(fname_after, 'w') as f: 13 f.write(ss)

投稿2025/08/26 14:59

little_street

総合スコア487

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

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

yyicp

2025/08/27 00:55

できました。 どうもありがとうございました。
guest

0

ベストアンサー

numpy.genfromtxt() で読み込んで、各ブロックの要素の順序を入れ替えます。なお、質問文に添付されている図の通りの順序だとすれば blks[:, [2, 0, 1, 3]] になるので、その様にしています。

python

1import os 2import numpy as np 3 4data_files = ['sample20.txt'] 5for f in data_files: 6 np.savetxt(os.path.splitext(f)[0] + 'mod.txt', 7 np.genfromtxt(f, dtype=str).reshape(-1, 4)[:, [2, 0, 1, 3]], 8 delimiter='\n', fmt='%s', newline='\n\n')

投稿2025/08/26 08:05

編集2025/08/27 07:53
melian

総合スコア21426

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

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

yyicp

2025/08/26 08:11

できました。 どうもありがとうございました。
melian

2025/08/26 13:22

以前の質問に対する回答へのコメントで、Bash + GNU awk で値を変更する例を挙げましたが、 ファイルから値を入力し、その値を変更する https://teratail.com/questions/v8ondx6qzwpylg 今回も同様の方法でデータの順序を入れ替えることができます。参考にしてみてください。 bash$ for f in sample*[!mod].txt do gawk -F'\n' -vRS='\n\n' -vOFS='\n' -vORS='\n\n' '{print $3,$1,$2,$4}' $f > ${f/.txt/mod.txt} done
yyicp

2025/08/27 01:09

参考情報、ありがとうございました。
yyicp

2025/08/27 08:22

こちらのコードも正しく動作しました。 どうもありがとうございました。
guest

0

TakaiY氏、聞きづらい事を聞いてくれたよな〜。
なんか、やたらファイルの入出力ばっか質問するんで、「ヘンな宿題ばっか出す学校だよな」とか思ってた(苦笑)。

まずさ。前にも書いたけど、Pandasとかnumpyとかのライブラリを使うかどうか、ってのはまずは「並べ替えのロジック」が出来て、「必要だったら」使う、って戦略になるわけ。
決め打ちで使うモンじゃないんだよ。
だからTakaiY氏も書いてるけど、

こういうことするなら、慣れているなら別だけど、numpy使わないほうがいいと思っている。

ホントそうなんだ。「導入したら操作がややこしくなる」くらいだったら使わん方がいいんだ。
また、前回もmelian氏が指摘してたけど、「全部文字列で文字列を弄る場合」だったら、極論Pythonなんて使わんでも構わない。
まぁ、恐らく「仕事でやってる」ってぇのならPCのOSがWindowsだ、って前提だろうから、AWKとか使えないだろうけどね。
昔はVBScriptとか?Windowsとかだと使うケースだったのかもしれないよ。今はどうなってんだか知らんが(非推奨になったんだっけ?)。

これも問題の本質は、

Python

1[[5, 0, 0, 8], [5, 0, 1, 4], [5, 1, 1, 1]] => [[0, 5, 0, 8], [0, 5, 1, 4], [1, 5, 1, 1]]

と言うデータ変換(新規リスト生成)の問題、なんだ。具体的には、[先頭, 次点]ってリストを2番目の要素を持った単一のリストとケツの要素を持った単一のリストで「挟んで」新しいリストを作れ、って事だよな。
Pythonだとこんなカンジで書く。

Python

1>>> [[lst[2]] + lst[:2] + [lst[-1]] for lst in [[5, 0, 0, 8], [5, 0, 1, 4], [5, 1, 1, 1]]] 2[[0, 5, 0, 8], [1, 5, 0, 4], [1, 5, 1, 1]] 3

リスト内包表記を使えば一丁上がり、だ。

よって、例えば全体的にはこんなカンジになるだろう。

Python

1#!/usr/bin/env python3 2 3import pandas as pd 4import sys 5 6if __name__ == '__main__': 7 file_name = sys.argv[1] 8 with open(file_name.replace('.', 'mod.'), 'w') as f: 9 f.write('\n\n'.join(['\n'.join(map(str, i)) for i in \ 10 [[lst[2]] + lst[:2] + [lst[-1]] for lst in \ 11 [blk[0].to_list() for blk in \ 12 pd.read_csv(file_name, header=None, chunksize=4)]]])) 13

コマンドライン引数でファイル名を受け取って、modを付け足した新しいファイルに変換したデータを書き出すようにしてる。

実行例

これで終わり、だ。

投稿2025/08/26 15:18

cametan

総合スコア178

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

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

melian

2025/08/26 19:37

Pandasを利用するのであれば、  - read_csv() でデータタイプ(dtype)を文字列(str)に指定  - pandas.Series.iloc() でデータの順序を変更  - pandas.Series.str.cat() で連結 としてもよいかと。 with open(file_name.replace('.', 'mod.'), 'w') as f:   f.write('\n\n'.join(blk.iloc[[2,0,1,3], 0].str.cat(sep='\n')             for blk in pd.read_csv(file_name, header=None, chunksize=4, dtype=str)))
cametan

2025/08/26 19:40

おお、そっちの方が良さそうですね。 Thanxです。
yyicp

2025/08/27 01:30 編集

>cametan様 お気遣いいただきどうもありがとうございます。 これからも遠慮なく意見を投げかけていただければと思います。 (これは他の皆様に対しても言えることですが) 今の状況は以下のような感じです。 ① 私がやりたいこと ② ①のための色々な準備 私がpythonを使用しているのは、①が書かれているpythonのコードが既にあるからです。②はC言語で書けると思うのですが、①と②で言語を分けるのもなあと思っているのと、最終的に①+②で1つのプログラムにしたいと思っているので、色々質問させていただいております。今回の質問も②の一部とお考え下さい。
cametan

2025/08/27 05:37

> yyicp氏 > ②はC言語で書けると思う 何でも書けるだろうけど、Cを導入するのは悪手かな。 ただ、このテの問題は、何度も書くけど、「入出力自体」はどうにでもなるんだ。 そうじゃなくって、「データを変換する」のは基本的にリストをどう弄るか、ってトコに集約される。 まずはリストをどう弄るのか、って観点を持つこと。 そこさえハッキリすれば、前回も今回も、結局入力で得る値がリストで得られる時点で、解決可能だ、って視点を持つ事が大事です。
yyicp

2025/08/27 08:25

>cametan様 コメントありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問