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

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

ただいまの
回答率

87.90%

sliceで切り取った文字列の代入

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 555
退会済みユーザー

退会済みユーザー

(file1)
ATOM   1  N   GLY A 
ATOM   2  CA  GLY A
ATOM  49  N   GLY A
ATOM  50  CA  GLY A


というファイルがあり、これの2列目を連番にしたいです。
(1 2 49 50 を 1 2 3 4 とする。)
そこで、連番のファイルを作成し、2列目の値と比較して、違っていれば連番の値を代入するというやり方を考えました。

(renban)
1
2
3
4
path = 'file1'
path2 = 'renban'

f = open(path)
list = f.readlines()
f2 = open(path2)
list2 = f2.readlines()

for (line, line2) in zip(list, list2):
    line_1 = line[6:8] # 1 2 49 50を抜きだし
    line2_1 = line2[0:1] # 1 2 3 4を抜きだし
    a = int(line_1)
    b = int(line2_1)
    if a != b:
       line_1 = line2_1
       fileobj = open("a.log","a")
       print >> fileobj, line.rstrip()
       # ATOM  49  N   GLY A -> ATOM  3  N   GLY A
       # ATOM  50  CA  GLY A -> ATOM  4  CA  GLY A と出力されてほしいが、うまくいっていない。
  elif a == b:
       fileobj = open("a.log","a")
       print >> fileobj, line.rstrip()
    # ATOM   1  N   GLY A 
      # ATOM   2  CA  GLY A が出力される。

f.close()
f2.close()


このようなスクリプトを書いてみたのですが、

if a != b:
       line_1 = line2_1
       fileobj = open("a.log","a")
       print >> fileobj, line.rstrip()


の部分が期待通りになりません。
果たしてこのようなやり方で合っているのか。もっと他にシンプルな書き方があるのか疑問に思っています。

お分かりの方ご教示お願いします。

(現在の結果)
ATOM   1  N   GLY A 
ATOM   2  CA  GLY A
ATOM  49  N   GLY A
ATOM  50  CA  GLY A

(得たい結果)
ATOM   1  N   GLY A 
ATOM   2  CA  GLY A
ATOM   3  N   GLY A
ATOM   4  CA  GLY A
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+1

2列目を連番にするのであればこれは如何でしょうか?
連番のindexを目的の箇所に差し替えます。

path = 'file1'
f = open(path).readlines()

index = 1
out = []
for line in f: 
    str_num = str(index).rjust(2) # 右寄せの空白埋めをする 1 -> ' 1'
    tmp = line[:6] + str_num + line[8:] # 'ATOM  ' + ' n' + '  N   GLY A \n'
    out.append(tmp)
    index += 1

# 出力
for line in out:
    fileobj = open("a.log","a")
    print >> fileobj, line.rstrip()

行数が3桁以上の場合はstr.rjust()の引数を変えて調整できます。
str.rjust()についてはこちらが詳しいです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

文字列の位置を指定してスライスする方式だと、数字の桁数が3,4,…と増えたときに大変そうなので正規表現を使ってみました。元々の1行のデータ 'ATOM   1  N   GLY A' を以下の3つに分割しています。

first = 'ATOM'
second = '   1'
third = '  N   GLY A'

このうち、secondの部分を文字数(len(second))で右寄せした連番に置換してあげれば期待するような結果になると思います。

import re

path = 'file1'
f = open(path)
rows = f.readlines()
f.close()

seq_start = 1
for i, row in enumerate(rows, seq_start):
    first, second, third = re.match(r'(\w+)( +\d+)(.*)', row).groups()
    print(first + str(i).rjust(len(second)) + third)

    # re.sub()を使うことにして、無理矢理1行にすることもできます
    # print(re.sub(r'( +\d+)', lambda x: str(i).rjust(len(x.group(1))), row.strip('\n')))

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

恐らく、現在のコードだと「 file1 のn行目の2列目の値が renban のn行目の値と異なっていたら(異なっていなくても) file1 のn行目を a.log に出力する。」というコードになっています。(ただ出力するだけなので、出力される内容がfile1と変わっていない)

質問主さんの意図としては「 file1 のn行目の2列目の値が renban のn行目の値と異なっていたら file1 のn行目をrenbanの値に入れ替えて a.log に出力する。」ことなので入れ替える
処理を実装出来れば解決に近づけると思います。(・ω・)

見当違いでしたら申し訳ありません。。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/10/24 12:45

    おっしゃるとおりです。
    その入れ替えるのをどうすればいいかわからず、困っています。
    教えていただけないでしょうか?

    キャンセル

  • 2018/10/24 12:56

    個人的に、kichirb3さんの解答が綺麗だなと感じました!(丸投げになってしまい申し訳ないですが。。。)

    キャンセル

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

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

関連した質問

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