🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

779閲覧

Python テキスト形式の表をソートして出力

nahi123

総合スコア14

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/02/04 22:09

編集2021/02/04 22:13

テキスト形式の表があり、指定の条件を元に数字を大きい順にソートして
テキスト形式で返したい。

入力はテキストですが、表にするとこんなインプット

category0category1category2totalunit
fishdryika-2018.34-9
fishrawika-131.85-3
fishdryaji18363.41117
fishrawaji14542.3949
¥subtotal¥subtotal¥subtotal599051.632728
fish¥subtotal¥subtotal330267.421406
fishraw¥subtotal166186.02864
fishdry¥subtotal164081.39542
meat¥subtotal¥subtotal178959.8742
meatcookedhorse29778.8197
meatrawlam23425.49101
meatcookedduck2387482
meatcooked¥subtotal99739.9341
meatrawbeef382.42
meatraw¥subtotal79219.9401

アプトプットは、Categoryの後ろの数字が小さい順に大きな分類になっており、分類毎にsubtotalがあり、例えばTotalの数字の大きな順に分類毎に順番に表示したい。

  • Category0のsubtotalは、一番上に表示
  • Category1に複数subtotalがある場合は、Totalの中で数字が大きい項目を次に表示。 次にfish/rawとfish/dryのsubtotalの数字を比べてfish/rawの方が数字が大きいので、次に表示。
  • fish/rawの中でTotalが大きい順にfish/raw/aji, fish/raw/ikaを順番に表示

以下は、表のイメージを抜粋しているので、subtotalの詳細の合計は、合っていません

category0category1category2totalunit
¥subtotal¥subtotal¥subtotal599051.632728
fish¥subtotal¥subtotal330267.421406
fishraw¥subtotal166186.02864
fishrawaji14542.3949
fishrawika-131.85-3
fishdry¥subtotal164081.39542
fishdryaji18363.41117
fishdryika-2018.34-9
meat¥subtotal¥subtotal178959.8742
meatcooked¥subtotal99739.9341
meatcookedhorse29778.8197
meatcookedduck2387482
meatraw¥subtotal79219.9401
meatrawlam23425.49101
meatrawbeef382.42

現状のコードは、テキストで返すようにしてませんが、まずはソートがうまくいことだけを試したが、うまくいきませんでした。どういう感じでソートを作成すればよいでしょうか?

input = """category0|category1|category2|total|unit fish|dry|ika|-2018.34|-9 fish|dry|aji|18363.41|117 meat|cooked|pork|328|1 fish|dry|hokke|29090.73|125 fish|dry|sanma|7187.84|8 fish|raw|ika|-131.85|-3 meat|cooked|other|1688.8|5 fish|raw|aji|14542.39|49 meat|cooked|chicken|3311|10 fish|raw|hokke|48355|209 fish|raw|sanma|4436.4|17 fish|dry|saba|42454.92|121 meat|cooked|beef|7795.45|25 fish|raw|saba|1628|12 meat|cooked|lam|32963.85|121 fish|raw|shishamo|4443.75|31 meat|raw|pork|15703|79 meat|raw|chicken|39299|213 fish|dry|shishamo|12790.85|45 fish|raw|tai|7788.79|32 meat|cooked|duck|23874|82 fish|dry|tai|2164.8|8 meat|¥subtotal|¥subtotal|178959.8|742 fish|dry|kinki|19317.84|601 meat|cooked|¥subtotal|99739.9|341 fish|raw|kinki|26081.2|128 fish|raw|nodoguro|40678.91|272 fish|dry|nodoguro|39314.15|144 meat|cooked|horse|29778.81|97 fish|dry|iwashi|13778.59|40 fish|¥subtotal|¥subtotal|330267.42|1406 fish|raw|¥subtotal|166186.02|864 meat|raw|beef|382.4|2 meat|raw|¥subtotal|79219.9|401 ¥subtotal|¥subtotal|¥subtotal|599051.63|2728 meat|raw|lam|23425.49|101 meat|raw|other|410|6 fish|dry|¥subtotal|164081.39|542""" output="""category0|category1|category2|total|unit ¥subtotal|¥subtotal|¥subtotal|599051.63|2728 fish|¥subtotal|¥subtotal|330267.42|1406 fish|raw|¥subtotal|166186.02|864 fish|raw|hokke|48355|209 fish|raw|nodoguro|40678.91|272 fish|raw|kinki|26081.2|128 fish|raw|aji|14542.39|49 fish|raw|tai|7788.79|32 fish|raw|shishamo|4443.75|31 fish|raw|sanma|4436.4|17 fish|raw|saba|1628|12 fish|raw|ika|-131.85|-3 fish|dry|¥subtotal|164081.39|542 fish|dry|saba|42454.92|121 fish|dry|nodoguro|39314.15|144 fish|dry|hokke|29090.73|125 fish|dry|kinki|19317.84|601 fish|dry|aji|18363.41|117 fish|dry|iwashi|13778.59|40 fish|dry|shishamo|12790.85|45 fish|dry|sanma|7187.84|8 fish|dry|tai|2164.8|8 fish|dry|ika|-2018.34|-9 meat|¥subtotal|¥subtotal|178959.8|742 meat|cooked|¥subtotal|99739.9|341 meat|cooked|lam|32963.85|121 meat|cooked|horse|29778.81|97 meat|cooked|duck|23874|82 meat|cooked|beef|7795.45|25 meat|cooked|chicken|3311|10 meat|cooked|other|1688.8|5 meat|cooked|pork|328|1 meat|raw|¥subtotal|79219.9|401 meat|raw|chicken|39299|213 meat|raw|lam|23425.49|101 meat|raw|pork|15703|79 meat|raw|other|410|6 meat|raw|beef|382.4|2 """ from collections import defaultdict def sort_text(input_data, sort_func): data = input_data.split('\n') ref = defaultdict(lambda: defaultdict(dict)) num_proverties = 0 columns = [] ans = "" for i, d in enumerate(data): tmp = d.split('|') if i == 0: columns += tmp for col in columns: if col.startswith('category'): num_proverties += 1 ans += ('|').join(tmp) + ('\n') else: for j, col in enumerate(columns): ref[i][col] = tmp[j]   #以下を色々試したがうまくいかなかった。 res = sorted(ref.items(), key=lambda x: [x[1]['category2'], -float(x[1][sort_func])]) res = sorted(res, key=lambda x: [x[1]['category1'], -float(x[1][sort_func])]) res = sorted(res, key=lambda x: [x[1]['category0'], -float(x[1][sort_func])]) return res if __name__ == '__main__': res = sort_text(input, 'total') for r in res: print(r)

よろしくおねがいします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

meg_

2021/02/05 00:21

> テキスト形式の表 csvなどてあればpandasモジュールを使用するのが簡単だとおもいます。
guest

回答1

0

ベストアンサー

なんかめっちゃ長くなりましたが、コード2つのうち上はただのテストデータ作成(DataFrameに入れただけ)
下がソート処理です。
cat2のsubtotalを、total順に並び替えして、その時のcat1の並びをリスト化
cat1のsubtotalを、total順に並び替えして、その時のcat0の並びをリスト化
多次元リストをitertoolsで1次元にならしてから、pd.concatで一体化

df

1input_data = """category0|category1|category2|total|unit 2fish|dry|ika|-2018.34|-9 3fish|dry|aji|18363.41|117 4meat|cooked|pork|328|1 5fish|dry|hokke|29090.73|125 6fish|dry|sanma|7187.84|8 7fish|raw|ika|-131.85|-3 8meat|cooked|other|1688.8|5 9fish|raw|aji|14542.39|49 10meat|cooked|chicken|3311|10 11fish|raw|hokke|48355|209 12fish|raw|sanma|4436.4|17 13fish|dry|saba|42454.92|121 14meat|cooked|beef|7795.45|25 15fish|raw|saba|1628|12 16meat|cooked|lam|32963.85|121 17fish|raw|shishamo|4443.75|31 18meat|raw|pork|15703|79 19meat|raw|chicken|39299|213 20fish|dry|shishamo|12790.85|45 21fish|raw|tai|7788.79|32 22meat|cooked|duck|23874|82 23fish|dry|tai|2164.8|8 24meat|¥subtotal|¥subtotal|178959.8|742 25fish|dry|kinki|19317.84|601 26meat|cooked|¥subtotal|99739.9|341 27fish|raw|kinki|26081.2|128 28fish|raw|nodoguro|40678.91|272 29fish|dry|nodoguro|39314.15|144 30meat|cooked|horse|29778.81|97 31fish|dry|iwashi|13778.59|40 32fish|¥subtotal|¥subtotal|330267.42|1406 33fish|raw|¥subtotal|166186.02|864 34meat|raw|beef|382.4|2 35meat|raw|¥subtotal|79219.9|401 36¥subtotal|¥subtotal|¥subtotal|599051.63|2728 37meat|raw|lam|23425.49|101 38meat|raw|other|410|6 39fish|dry|¥subtotal|164081.39|542""" 40 41import io 42import pandas as pd 43df = pd.read_table(io.StringIO(input_data), delimiter="|") 44

python3

1import itertools 2 3def sort_cat(cat, cat_num, df): 4 return df.groupby(f"category{cat_num}").get_group(cat).sort_values(by="total", ascending=False) 5 6def sorted1_df(df): 7 cat_num = 1 8 sub_sort = df.groupby(f"category{cat_num+1}").get_group("¥subtotal").sort_values(by="total", ascending=False)[f"category{cat_num}"] 9 return [sort_cat(cat, cat_num, df) for cat in sub_sort] 10 11def sorted0_df(df): 12 cat_num = 0 13 sub_sort = df.groupby(f"category{cat_num+1}").get_group("¥subtotal").sort_values(by="total", ascending=False)[f"category{cat_num}"] 14 # print(sub_sort) 15 # 34 ¥subtotal 16 # 30 fish 17 # 22 meat 18 return [sorted1_df(sub_df) for sub_df in [sort_cat(cat, cat_num, df) for cat in sub_sort]] 19 20new_df = pd.concat(list(itertools.chain.from_iterable(sorted0_df(df)))) 21# print(new_df) 22# category0 category1 category2 total unit 23# 34 ¥subtotal ¥subtotal ¥subtotal 599051.63 2728 24# 30 fish ¥subtotal ¥subtotal 330267.42 1406 25# 31 fish raw ¥subtotal 166186.02 864 26# 9 fish raw hokke 48355.00 209 27# 26 fish raw nodoguro 40678.91 272 28# 25 fish raw kinki 26081.20 128 29# 7 fish raw aji 14542.39 49 30# 19 fish raw tai 7788.79 32 31# 15 fish raw shishamo 4443.75 31 32# 10 fish raw sanma 4436.40 17 33# 13 fish raw saba 1628.00 12 34# 5 fish raw ika -131.85 -3 35# 37 fish dry ¥subtotal 164081.39 542 36# 11 fish dry saba 42454.92 121 37# 27 fish dry nodoguro 39314.15 144 38# 3 fish dry hokke 29090.73 125 39# 23 fish dry kinki 19317.84 601 40# 1 fish dry aji 18363.41 117 41# 29 fish dry iwashi 13778.59 40 42# 18 fish dry shishamo 12790.85 45 43# 4 fish dry sanma 7187.84 8 44# 21 fish dry tai 2164.80 8 45# 0 fish dry ika -2018.34 -9 46# 22 meat ¥subtotal ¥subtotal 178959.80 742 47# 24 meat cooked ¥subtotal 99739.90 341 48# 14 meat cooked lam 32963.85 121 49# 28 meat cooked horse 29778.81 97 50# 20 meat cooked duck 23874.00 82 51# 12 meat cooked beef 7795.45 25 52# 8 meat cooked chicken 3311.00 10 53# 6 meat cooked other 1688.80 5 54# 2 meat cooked pork 328.00 1 55# 33 meat raw ¥subtotal 79219.90 401 56# 17 meat raw chicken 39299.00 213 57# 35 meat raw lam 23425.49 101 58# 16 meat raw pork 15703.00 79 59# 36 meat raw other 410.00 6 60# 32 meat raw beef 382.40 2

投稿2021/02/05 01:29

jeanbiego

総合スコア3966

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nahi123

2021/02/06 00:11

ありがとうございます。Pandasで、順番にソートするんですね。助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問