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

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

ただいまの
回答率

90.48%

  • Python 3.x

    6880questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • 機械学習

    715questions

    機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

  • pandas

    630questions

    Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

クラスタリングの番号をある条件で番号を振りなおしたい

解決済

回答 1

投稿 編集

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

barobaro

score 148

やりたいことを簡単にしました

df = pd.read_table(io.StringIO("""
top    row
1    2
2    2
3    0
4    0
5    1
6    1
"""))

クラスタリングするとこういう結果がでたのですが
top    row
1    2
2    2
3    0
4    0
5    1
6    1

こういうtop順にrowを0から番号を振りなおしたい
top    row
1    0
2    0
3    1
4    1
5    2
6    2

よろしくお願いします。

以下サンプルは不要です。

PDFの表からテキスト抽出してTSVの表を作成したいのですが

  1. popplerのpdftohtmlからxmlを作成
  2. xmlからX/Y座標とテキストのcsvを作成
  3. X座標とY座標をクラスタリングしクラス分け

クラスタリングはできたのですが順番がバラバラなのでX座標の順、Y座標の順で番号を振り直したい。

df2_results['top'] Y座標
df2_results['left'] X座標
df2_results['row'] Yのクラス
df2_results['col'] Xのクラス

になっています。

よろしくお願いします。

import pandas as pd
from sklearn.cluster import KMeans

df = pd.read_csv('data.csv')

# ページ・縦・横の順にソート
df.sort_values(by=['page', 'top', 'left'], inplace=True)
df.head()

df1 = df.loc[:, ['page', 'top', 'left', 'text']]
df1.plot.scatter(x='left', y='top', ylim=(892, 0))

イメージ説明

# ヘッダー部を除外
df2 = df1[df1['top'] > 100]
df2

# 表部分確認
df2.plot.scatter(x='left', y='top', ylim=(892, 0))

# Y座標をクラスタリング
mdl_y = KMeans(n_clusters=33)
df2_y = df2[['top']]
mdl_y.fit(df2_y)
y2 = mdl_y.labels_
print(y2)

# X座標をクラスタリング
mdl_x = KMeans(n_clusters=6)
df2_x = df2[['left']]
mdl_x.fit(df2_x)
x2 = mdl_x.labels_
print(x2)

df2_results = df2.copy()

df2_results['row'] = y2
df2_results['col'] = x2

df2_results.sort_values('top')
# Y座標散布図
df2_results.plot.scatter(
    x='left', y='top', c='row', cmap='winter', ylim=(892, 0))


Y座標散布図
イメージ説明

# X座標散布図
df2_results.plot.scatter(
    x='left', y='top', c='col', cmap='winter', ylim=(892, 0))


X座標散布図
イメージ説明

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

こんな感じでできます。

>>> x_cluster_centers_ = np.array([[0], [15], [-30]])  # 適当に見立ててデータを作る
>>> x_labels_ = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2])  # 適当に見立ててデータを作る
>>> x_centers = x_cluster_centers_.ravel()  # 取扱いやすいようベクトル(ndim=1の配列)にする
>>> x_convert_dic = {k:v for v,k in enumerate(x_centers.argsort())}  # argsortしてindexと値を逆転させた辞書を作る
>>> [x_convert_dic[l] for l in x_labels_]  # その辞書を使って変換
[1, 1, 1, 2, 2, 2, 0, 0, 0]

 色がわかりづらい件については

色がわかりやすいcmapを探して、winterの代わりに指定する。
Choosing Colormaps — Matplotlib 2.0.2 documentation

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/15 21:31

    コードを参考に今から試してみます。
    色について種類があるのに気づかなくて少し見やすくなりました
    ありがとうございます。

    キャンセル

  • 2018/06/15 22:55

    やってみたのですがargsortをうまく使えなくて動きませんでした。
    サンプルをシンプルに書き換えましたのでよければもう一度お願いします。

    キャンセル

  • 2018/06/15 22:58

    ん、動きません? どんな感じでやったのか見せていただけると直せるかもしれません
    追加注文の方は、どうやるのがうまいかすぐ思いつかないので、考えておいて明日回答します

    キャンセル

  • 2018/06/15 23:44 編集

    いつでもかまいませんのでお時間がお手すきの際によろしくお願いします。

    サンプルを利用しています
    y_conv_dic = {k:v for v,k in enumerate(df['top'].argsort())}
    df['test'] = [y_conv_dic[l] for l in df['row']]
    df

    top row test
    0 1 3 3
    1 2 3 3
    2 3 1 1
    3 4 1 1
    4 5 2 2
    5 6 2 2

    キャンセル

  • 2018/06/15 23:58

    df['top']の代わりにmdl_x.cluster_centers_.ravel()とかを入れればうまくいくと思います
    その情報を使わないでやろうとすると、各クラスタごとに集計してtopの平均を取ってその平均でソート、でしょうか。それはそれでやればできますけど、ちょっと面倒ですよ

    y_conv_dic = {k:v for v,k in enumerate(df.groupby("row").mean()["top"].argsort())}
    df['test'] = [y_conv_dic[l] for l in df['row']]
    print(df)

    キャンセル

  • 2018/06/16 00:27

    できましたどうもありがとうございます。
    まだいろいろとわからないことばかりなので勉強します。

    キャンセル

関連した質問

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

  • Python 3.x

    6880questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • 機械学習

    715questions

    機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

  • pandas

    630questions

    Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。