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

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

ただいまの
回答率

90.33%

  • Python 2.7

    1343questions

    Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

ロウデータより要素を取り出して、マトリックス表を作成したい。

受付中

回答 2

投稿

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

jizo_25

score 2

Pythonで下記のようなCSVファイルを読み込んで、マトリクスを作成したいのですが、うまく行きません。
よろしければどのように書けばよいか、ご教授いただけないでしょうか。
Pandasのライブラリを使わない方法があれば、そちらを知りたいです。
Pandasの書き方でしか実装不可能な場合は、そちらでも構いません。
よろしくお願いいたします。

読み込みCSV

名前,学年,特徴,記載者
A子,3年,長身,B助
A子,3年,スレンダー,C世
A子,3年,マイペース,D太
A子,3年,泣き虫,D太
B助,2年,静か,A子
B助,2年,チビ,D太
B助,2年,人見知り,D太
C世,3年,マイペース,A子
C世,3年,人見知り,D太

抽出フォーマット

名前 長身 スレンダー マイペース 泣き虫 静か チビ 人見知り
A子
B助
C世
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+2

pandas.pivot_tableを使えば、以下のように行毎の値を列毎に変換できます。

import pandas as pd
import numpy as np
from io import StringIO
pd.set_option('display.unicode.east_asian_width', True)

# サンプルデータ読込
csvStr = u"""
名前,学年,特徴,記載者
A子,3年,長身,B助
A子,3年,スレンダー,C世
A子,3年,マイペース,D太
A子,3年,泣き虫,D太
B助,2年,静か,A子
B助,2年,チビ,D太
B助,2年,人見知り,D太
C世,3年,マイペース,A子
C世,3年,人見知り,D太
"""
csvIo = StringIO(csvStr)
df = pd.read_csv( csvIo, sep=",", skipinitialspace=True)

df = df.drop(['学年','記載者'], axis=1) # 不要な列を削除
df['dummy'] = 1 # pivot_tableでの値集計用のダミー列を追加
print(df)

# 特徴を列持ちに
df2 = df.pivot_table(values='dummy', index='名前', columns='特徴',fill_value = 0)
print(df2)


結果

  名前        特徴  dummy
0  A子        長身      1
1  A子  スレンダー      1
2  A子  マイペース      1
3  A子      泣き虫      1
4  B助        静か      1
5  B助        チビ      1
6  B助    人見知り      1
7  C世  マイペース      1
8  C世    人見知り      1
特徴  スレンダー  チビ  マイペース  人見知り  泣き虫  長身  静か
名前                                                              
A子              1     0           1         0       1     1     0
B助              0     1           0         1       0     0     1
C世              0     0           1         1       0     0     0

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

+1

Pandas 等のライブラリを使った方が楽な気がしますが、人力でやる方法を:

今回作りたい成果物(抽出フォーマット)は一般的にピボットテーブルと呼ばれます。Excelでおなじみのやつです。ピボットテーブルを作るには

  1. 元データの集計
  2. ピボットテーブルの作成

の2ステップが必要になります。


 STEP1. 元データの集計

今回、人物:特徴 が 1:n の関係にあり、人物および人物に対する特徴は重複しない(A子さんの特徴は「長身かつ長身」みたいなデータはNG)ので、人物の辞書(dict型)に特徴の集合(set型)を格納するデータフォーマットにするのが良いと思います。

csvモジュールでCSVデータを読み込み、defaultdictモジュールを使ってデータの集計を行います。

from collections import defaultdict
import csv

csv_data = """A子,3年,長身,B助
A子,3年,スレンダー,C世
A子,3年,マイペース,D太
A子,3年,泣き虫,D太
B助,2年,静か,A子
B助,2年,チビ,D太
B助,2年,人見知り,D太
C世,3年,マイペース,A子
C世,3年,人見知り,D太"""

persons = defaultdict(set)  # 辞書を定義

for row in csv.reader(csv_data.split()):
    persons[row[0]].add(row[2])  # 辞書に各個人の特徴を入れていく

"""結果:
defaultdict(<class 'set'>,
            {'A子': {'スレンダー', '泣き虫', 'マイペース', '長身'},
             'B助': {'人見知り', 'チビ', '静か'},
             'C世': {'人見知り', 'マイペース'}})
"""

 STEP2. ピボットテーブルの作成

まず成果物のカラム(列)を定義します。上記で集計した特徴データの和集合をヘッダとするのがよいと思います。

# union() 関数を使って各人物の特徴の和集合を作りリストとして格納
characters = list(set().union(*persons.values()))

# ヘッダを表示
print(','.join(['名前'] + characters))

最後に実データの作成です。for 文で人物の辞書(persons)を走査しつつ、該当の特徴が存在したら 、しなかったら 空文字を表示するようにします。

for p in persons:
    print(p, end='')
    for c in characters:
        if c in persons[p]:
            print(',○', end='')
        else:
            print(',', end='')
    print('')

"""結果:
名前,人見知り,スレンダー,チビ,マイペース,泣き虫,長身
A子,,○,,○,○,○
B助,○,,○,,,
C世,○,,,○,,
"""

余談ですが、このままだとコードが長いので Python の内包表記というテクニックを使うとシンプルに書けます。

for p in persons:
    print(','.join([p] + ['◯' if c in persons[p] else '' for c in characters]))

"""結果:
名前,長身,人見知り,スレンダー,チビ,泣き虫,マイペース
A子,◯,,◯,,◯,◯
B助,,◯,,◯,,
C世,,◯,,,,◯
"""

こんなかんじでしょうか・・

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

  • Python 2.7

    1343questions

    Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。