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

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

ただいまの
回答率

89.10%

pythonでtsvファイルを加工して新しいtsvファイルを作りたい

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 1,653

lack_un

score 50

前提・実現したいこと

現在音楽の情報系のwebアプリを作ろうとしています。
DBPediaからもってきたtsvのファイルを加工して

ART-SCHOOL,パワー・ポップ
ART-SCHOOL,インディー・ロック
ART-SCHOOL,オルタナティヴ・ロック
ART-SCHOOL,ニュー・ウェーヴ_(音楽)
ART-SCHOOL,ポスト・グランジ
Doa (ミュージシャン),J-POP
Doa (ミュージシャン),ロック_(音楽)

こういう情報を

[['ART-SCHOOL', 'パワー・ポップ', 'パワー・ポップ', 'インディー・ロック', 'オルタナティヴ・ロック', 'ニュー・ウェーヴ_(音楽)', 'ポスト・グランジ'],['Doa(ミュージシャン)','J-POP','ロック_(音楽)']]

という形に加工しようと思っています。なお、データはこの二つのアーティストだけでなく、他にもたくさんいます。

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

['ART-SCHOOL', 'パワー・ポップ']
0
[['ART-SCHOOL', 'パワー・ポップ', 'パワー・ポップ']]
['ART-SCHOOL', 'インディー・ロック']
0
[['ART-SCHOOL', 'パワー・ポップ', 'パワー・ポップ', 'インディー・ロック']]
['ART-SCHOOL', 'オルタナティヴ・ロック']
0
[['ART-SCHOOL', 'パワー・ポップ', 'パワー・ポップ', 'インディー・ロック', 'オルタナティヴ・ロック']]
['ART-SCHOOL', 'ニュー・ウェーヴ_(音楽)']
0
[['ART-SCHOOL', 'パワー・ポップ', 'パワー・ポップ', 'インディー・ロック', 'オルタナティヴ・ロック', 'ニュー・ウェーヴ_(音楽)']]
['ART-SCHOOL', 'ポスト・グランジ']
0
[['ART-SCHOOL', 'パワー・ポップ', 'パワー・ポップ', 'インディー・ロック', 'オルタナティヴ・ロック', 'ニュー・ウェーヴ_(音楽)', 'ポスト・グランジ']]
['Doa (ミュージシャン)', 'J-POP']
0
['Doa (ミュージシャン)', 'ロック_(音楽)']
5
Traceback (most recent call last):
  File "musician3.py", line 19, in <module>
    if output_data[recognize_name_num][0] == array_row[0]:
IndexError: list index out of range

該当のソースコード

# -*- coding: utf-8 -*-
import csv

output_data = [['ART-SCHOOL','パワー・ポップ']]
row_num = 0 #行数を把握するための番号
recognize_name_num = 0 #rowは無差別に進むので、artistの名前をチェックするための数をチェックする方の番号を調べる。

#全行をまず配列に変換する。
with open('second_rock_musician.tsv','r') as f:
    reader = csv.reader(f,delimiter='\n')
    for row in reader:
        str_row = ",".join(row) #いったん文字列へ
        #print(str_row)
        array_row = str_row.split(',') #扱いやすい配列へ。
            #rowが思った通りの配列じゃないことが原因。
        print(array_row)
        print(recognize_name_num)

        if output_data[recognize_name_num][0] == array_row[0]:
            rock_genre = array_row[1]
            output_data[recognize_name_num].append(rock_genre)
            print(output_data)
        else:
            output_data.append(row)
            recognize_name_num = row_num

        row_num = row_num + 1

試したこと

初期データで入れておかないとエラーが出るので、とりあえず1行最初に入れてあります。
index out of rangeの原因はrecognize_name_numで存在しないところがおかしいことだろう、と判断はつくのですがどういう手法で解決したらいいかがわからない状態です。あとはこれでできたらtsvで出力しようと思っています。
考えに考えたのですがうまくいきませんでした、みなさまの知恵を貸してください...!よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

無理にゴールとなる形式(listの中にlist)で処理しようとせずに、一度dictなどの扱いやすい形式にして最後に目的の形にしたほうが良いかと。

import csv

# listではなく、dictで入力データを管理
output_data = {}
with open('second_rock_musician.tsv','r') as f:
    reader = csv.reader(f)
    for row in reader:
        str_row = ",".join(row) #いったん文字列へ
        array_row = str_row.split(',') #扱いやすい配列へ。
        artist = array_row[0]
        genre = array_row[1]
        output_data.setdefault(artist, [])
        output_data[artist].append(genre)

# dictデータを目的のlist形式に変換
output_data = [[artist, ] + genre for artist, genre in output_data.items()]
output_data.sort(key=lambda data: data[0]) # 一応、アーティスト名でソート

print(output_data)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/09/02 14:11

    ありがとうございました。
    あたらしい知見がひらけました。

    キャンセル

0

単に加工するだけで良くて、データの量がそれほど多くないなら、まとめてグループ化するのが簡単です。

グループ化には、itertools.groupby()を使います。

import csv
import itertools

with open("second_rock_musician.tsv") as f:
    reader = csv.reader(f, delimiter=',')
    input = [row for row in reader]

output_data = [[k] + [x[1] for x in g] for k, g in itertools.groupby(input, lambda x: x[0])]
print(output_data)
# => [['ART-SCHOOL', 'パワー・ポップ', 'インディー・ロック',
# 'オルタナティヴ・ロック', 'ニュー・ウェーヴ_(音楽)', 'ポスト・グランジ'],
#  ['Doa (ミュージシャン)', 'J-POP', 'ロック_(音楽) ']]
# ※実際の出力は改行されていません

ちなみに、csv.reader()delimiter列の区切り文字です。この場合はカンマ区切りなので、","を指定します。また、","はデフォルトなので、省略できます。(省略の例は、attakeiさんが書かれているとおりです。)

参考リンク:

itertools.groupby(iterable, key=None) (10.1. itertools — 効率的なループ実行のためのイテレータ生成関数 — Python 3.5.2 ドキュメント
http://docs.python.jp/3.5/library/itertools.html#itertools.groupby

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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