syun_nissi
@syun_nissi (syun nissi)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

pandasのgroupbyでうまく集計ができない件

解決したいこと

複数のcsvデータを読み込み、リストに格納した上で結合し、データフレームを作成しています。(また不要な列を削除しています。)

該当するソースコード

import pandas as pd
import glob

csv_files = glob.glob('KENSU_DP11010_*.csv')

data_list = []

for file in csv_files:
    data_list.append(pd.read_csv(file,index_col=[0,3],encoding="shift-jis"))

data = pd.concat(data_list, axis=0)
data.drop(['普徴特徴','箱番号'] ,axis=1)

上記コードによる出力結果は下記の通りです。
無題.png

ここから、groupbyで郵便番号毎、重量毎の件数を集計したいのですが、下記画面の通りとなり、郵便番号164 25g以下が2行にわたり表示され、集計できません。(165も同様)

該当するソースコード

data.groupby(['郵便番号','重量帯']).sum()["件数"]

無題2.png

お分かりになれば、ご教示いただけますと幸いです。

0

3Answer

表示から推測すると、郵便番号が同じに見えるものに、不可視の相違点があるのではないでしょうか。
例えば、「"164"と"164 "」のような場合や、さらには、「"165"と"165​" (165165​)」のように見た目で区別が付かない場合も考えられます。

以下のような感じで、「郵便番号の文字数」の列を挿入してをチェックしてみてはいかがでしょうか。

data['郵便番号の文字数'] = data['郵便番号'].astype(str).apply(lambda key:len(key))
data.groupby(['郵便番号','郵便番号の文字数','重量帯']).sum()["件数"]
追記

あるいは、以下のようにして、郵便番号の相違を解消する方法も考えられます。

data['郵便番号'] = data['郵便番号'].astype(str).apply(int)
data.groupby(['郵便番号','重量帯']).sum()["件数"]
追記2

以下のようにすると、郵便番号の前後の空白を除去することができます。

data['郵便番号'] = data['郵便番号'].astype(str).apply(lambda key:key.strip())
data.groupby(['郵便番号','重量帯']).sum()["件数"]
追記3

以下、追記2の実証コードとその結果です。(Python 3.8.5)

code
import pandas as pd

data = pd.DataFrame({'key':[164, "164 ", 164, 164, 165, 165, 165, 170, 170], 'x':[1,1,1,4,1,1,7,1,1], 'value':[300, 300, 200, 300, 250, 200, 200, 250, 300]})
data['key'] = data['key'].astype(str).apply(lambda key:key.strip())
data['length'] = data['key'].astype(str).apply(lambda key:len(key))
data.groupby(['key', 'length', 'x']).sum()['value']
result
key  length  x
164  3       1    800
             4    300
165  3       1    450
             7    200
170  3       1    550
Name: value, dtype: int64
1Like

Comments

  1. @syun_nissi

    Questioner

    tetr4lab様、さっそくアドバイスをいただきありがとうございます。
    astype(str).apply(lambda key:len(key)を適用したところ原因がわかりました。
    仰る通り「"164"と"164 "」のように半角スペースが入っていました。
    ただ、スペースを取り除こうして、astype(str).apply(int)ですと「区外」という文字があるためエラーになってしまい、別のやり方で実施しましたがうまくいきません。現象を投稿いたします。



  2. > str.replace(" ","")で半角スペースを取り除こうとしましたが、下記の図の通りうまくいきません。。

    空白の除去について追記しました。
  3. > アドバイスいただいた方法(astype(str).apply(lambda key:key.strip())を試しましたがやはりうまくいかないようです。
    実証コードを追記しました。

    > なぜだかさっぱりです。。いったんペンディングしようかと思います。
    承りました。お役に立てず申し訳ございません。
  4. @syun_nissi

    Questioner

    実証コードの方拝見しました。確かにデータがきちんとしていれば動作するプログラムであることが分かりました。わざわざご丁寧にありがとうございます。
    改めてデータの中身を検証してみたいと思います。

2021_02_08_22_15_44_JupyterLab.png

半角スペースが入っていたため、集計できませんでした。
2021_02_08_22_17_41_JupyterLab.png

str.replace(" ","")で半角スペースを取り除こうとしましたが、下記の図の通りうまくいきません。。
2021_02_08_22_39_40_Book1.xlsx_Excel.png

なぜだか全くわからず、もしお分かりになりましたらご教示いただけますと幸いです。

0Like

ご連絡が遅くなりました。アドバイスいただいた方法(astype(str).apply(lambda key:key.strip())を試しましたがやはりうまくいかないようです。
なぜだかさっぱりです。。いったんペンディングしようかと思います。
2021_02_11_12_44_05_strip_kensu.csv_メモ帳.png

0Like

Your answer might help someone💌