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世 | ◯ | ◯ |
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
pandas.pivot_tableを使えば、以下のように行毎の値を列毎に変換できます。
Python
1import pandas as pd 2import numpy as np 3from io import StringIO 4pd.set_option('display.unicode.east_asian_width', True) 5 6# サンプルデータ読込 7csvStr = u""" 8名前,学年,特徴,記載者 9A子,3年,長身,B助 10A子,3年,スレンダー,C世 11A子,3年,マイペース,D太 12A子,3年,泣き虫,D太 13B助,2年,静か,A子 14B助,2年,チビ,D太 15B助,2年,人見知り,D太 16C世,3年,マイペース,A子 17C世,3年,人見知り,D太 18""" 19csvIo = StringIO(csvStr) 20df = pd.read_csv( csvIo, sep=",", skipinitialspace=True) 21 22df = df.drop(['学年','記載者'], axis=1) # 不要な列を削除 23df['dummy'] = 1 # pivot_tableでの値集計用のダミー列を追加 24print(df) 25 26# 特徴を列持ちに 27df2 = df.pivot_table(values='dummy', index='名前', columns='特徴',fill_value = 0) 28print(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
投稿2017/09/06 01:10
総合スコア38266
0
Pandas 等のライブラリを使った方が楽な気がしますが、人力でやる方法を:
今回作りたい成果物(抽出フォーマット)は一般的にピボットテーブルと呼ばれます。Excelでおなじみのやつです。ピボットテーブルを作るには
- 元データの集計
- ピボットテーブルの作成
の2ステップが必要になります。
STEP1. 元データの集計
今回、人物:特徴 が 1:n の関係にあり、人物および人物に対する特徴は重複しない(A子さんの特徴は「長身かつ長身」みたいなデータはNG)ので、人物の辞書(dict型)に特徴の集合(set型)を格納するデータフォーマットにするのが良いと思います。
csvモジュールでCSVデータを読み込み、defaultdictモジュールを使ってデータの集計を行います。
python
1from collections import defaultdict 2import csv 3 4csv_data = """A子,3年,長身,B助 5A子,3年,スレンダー,C世 6A子,3年,マイペース,D太 7A子,3年,泣き虫,D太 8B助,2年,静か,A子 9B助,2年,チビ,D太 10B助,2年,人見知り,D太 11C世,3年,マイペース,A子 12C世,3年,人見知り,D太""" 13 14persons = defaultdict(set) # 辞書を定義 15 16for row in csv.reader(csv_data.split()): 17 persons[row[0]].add(row[2]) # 辞書に各個人の特徴を入れていく 18 19"""結果: 20defaultdict(<class 'set'>, 21 {'A子': {'スレンダー', '泣き虫', 'マイペース', '長身'}, 22 'B助': {'人見知り', 'チビ', '静か'}, 23 'C世': {'人見知り', 'マイペース'}}) 24"""
STEP2. ピボットテーブルの作成
まず成果物のカラム(列)を定義します。上記で集計した特徴データの和集合をヘッダとするのがよいと思います。
python
1# union() 関数を使って各人物の特徴の和集合を作りリストとして格納 2characters = list(set().union(*persons.values())) 3 4# ヘッダを表示 5print(','.join(['名前'] + characters))
最後に実データの作成です。for 文で人物の辞書(persons)を走査しつつ、該当の特徴が存在したら ○
、しなかったら 空文字を表示するようにします。
python
1for p in persons: 2 print(p, end='') 3 for c in characters: 4 if c in persons[p]: 5 print(',○', end='') 6 else: 7 print(',', end='') 8 print('') 9 10"""結果: 11名前,人見知り,スレンダー,チビ,マイペース,泣き虫,長身 12A子,,○,,○,○,○ 13B助,○,,○,,, 14C世,○,,,○,, 15"""
余談ですが、このままだとコードが長いので Python の内包表記というテクニックを使うとシンプルに書けます。
python
1for p in persons: 2 print(','.join([p] + ['◯' if c in persons[p] else '' for c in characters])) 3 4"""結果: 5名前,長身,人見知り,スレンダー,チビ,泣き虫,マイペース 6A子,◯,,◯,,◯,◯ 7B助,,◯,,◯,, 8C世,,◯,,,,◯ 9"""
こんなかんじでしょうか・・
投稿2017/09/06 01:24
編集2017/09/07 01:46総合スコア3095
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。