前提・実現したいこと
スプレッドシートまたはCSVにて下記図Aのように1行で格納している複数の列データを、スプレッドシートまたはCSVにて図Bのように複数行に分解して出力したいです。会社によって単価・数量が変化します。1しかない場合もあるし、3まである場合もあり、会社によりまちまちです。
使用する言語はPythonまたはGASにて行いたいです。
◾️図A
|会社名|単価1|数量1|単価2|数量2|単価3|数量3|
|:--|:--:|--:|
|株式会社A|380|50|3000|2|5000|10|
|株式会社B|50|100|8000|1|||
◾️図B
会社名 | 単価 | 数量 |
---|---|---|
株式会社A | 380 | 50 |
株式会社A | 3000 | 2 |
株式会社A | 5000 | 10 |
株式会社B | 50 | 100 |
株式会社B | 8000 | 1 |
どのように記述していいかアイデアが出てこないのでご教授宜しくお願い致します。
補足情報(FW/ツールのバージョンなど)
mac OS High Sierra, Python3
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
javascript
1function q220924() { 2 const csvId = '****'; 3 const dat = Utilities.parseCsv(DriveApp.getFileById(csvId).getBlob().getDataAsString(), ',').slice(1).reduce(function (a, c) { 4 return a.concat(c); 5 }, []); 6 SpreadsheetApp.getActive().insertSheet().getRange(1, 1, dat.length + 1, 3).setValues([["会社", "単価", "数量"]].concat(dat)); 7} 8 9function chunk(row) { 10 const company = row[0]; 11 return row.slice(1).filter(function (e) { 12 return e !== ""; 13 }).reduce(function (a, _, i, array) { 14 if (!(i % 2)) { 15 a.push([company, array[i], array[i + 1]]); 16 ; 17 } 18 return a; 19 }, []) 20}
投稿2019/11/05 15:40
総合スコア12705
0
Pythonで実施する場合はこんな感じできると思います。
Python
1import pandas as pd 2 3# NaNが混在している列が浮動小数点になるのを回避するため「dtype=str」をつけて文字列として扱う 4df = pd.read_csv('input.csv', dtype=str) 5 6print(df) 7""" 8 会社名 単価1 数量1 単価2 数量2 単価3 数量3 90 株式会社A 380 50 3000 2 5000 10 101 株式会社B 50 100 8000 1 NaN NaN 11""" 12 13columns = [ ['単価1', '数量1'], ['単価2', '数量2'], ['単価3', '数量3'] ] 14 15# 列名を変えながら結合 16df = pd.concat([ df.loc[:,['会社名', x[0], x[1]]].rename(columns={ x[0] : '単価', x[1]: '数量'}) for x in columns ]) 17 18# NaNがある行をdrop&ソート&index振り直し 19df = df.dropna(how='all',subset=['単価', '数量']).sort_values(by=['会社名']).reset_index(drop=True) 20 21print(df) 22""" 23 会社名 単価 数量 240 株式会社A 380 50 251 株式会社A 3000 2 262 株式会社A 5000 10 273 株式会社B 50 100 284 株式会社B 8000 1 29""" 30 31df.to_csv('output.csv', index=False)
投稿2019/11/02 23:26
総合スコア1627
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
はいでは、プログラムの基本的なことを教わってなく、完全独学で勉強してる私がとりあえず先に回答しておきます。
GAS
1function myFunction() { 2 3 var sh = "シート化します" 4 var arr = sh.getRange("タイトル除いた最初~最後まで").getValues() 5 var arr2 = [] 6 var record = [] 7 var kaisya = [] 8 9 10 for (var a = 0; a < arr.length;a++) 11 { 12 kaisya = arr[a][0]//会社名だけ別においとく。2行目になったら二行目の会社名をとる 13 for (var b = 0; b < arr[a].length; b++) 14 { 15 16 var num = arr[a][b*2+1]//単価情報 17 var num2 = arr[a][b*2+2]//数量情報 18 if(num == undefined || num == ""){break;} 19 record.push(kaisya,num,num2)//図Bのようにrecord = [会社名,単価,数量]にする 20 arr2.push(record)//そのレコードをプッシュする 21 record = []//レコードをまっさらにする。 22 } 23 24 } 25 26 sh.getRange("開始Row","開始Col",arr2.length,arr2[0].lenth).setValues(arr2) 27 28} 29
実際にシート化したりレンジ充てたりしてないのでちゃんと動くかは不明ですので発想だけを伝えますと、
forの中にfor文をいれて、
1つめのfor文には会社名をコピーして、2つめのfor文で2つづつ取っていって、それをレコード化しています。
ごり押しな考え方なので、単価、数量以外に何かはいったりしたら正しい結果になりません。
もう少し待てばもっと素晴らしい回答が頂けると思うので、とりあえず先にこの発想で組んでみて下さい。
投稿2019/11/02 16:12
編集2019/11/03 03:00総合スコア315
0
ベストアンサー
c.py
python3
1import csv 2import pprint 3 4with open('data.csv') as f: 5 reader = csv.DictReader(f) 6 rows = [row for row in reader] 7 8# pprint.pprint(rows) 9rows2 = [] 10for row in rows: 11 camp = row["会社名"] 12 for key in row.keys(): 13 if key.startswith("単価"): 14 key_num = key.replace("単価", "数量", 1) 15 if row[key] and row[key_num]: 16 rows2.append({"会社名": camp, "単価": row[key], "数量": row[key_num]}) 17 18# pprint.pprint(rows2) 19 20with open('data2.csv', 'w') as f: 21 writer = csv.DictWriter(f, ["会社名", "単価", "数量"]) 22 writer.writeheader() 23 for row in rows2: 24 writer.writerow(row)
参考情報
- PythonでCSVファイルを読み込み・書き込み(入力・出力)
投稿2019/11/03 01:46
総合スコア22324
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。