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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

Python

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

pandas

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

Q&A

解決済

2回答

2483閲覧

Dataframeの列を一定の文字数に変換したい。

hiroyuki828

総合スコア22

Python 3.x

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

Python

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

pandas

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

0グッド

0クリップ

投稿2019/04/08 13:54

前提・実現したいこと

python 3.5.4 / pandas 0.23.4 で、CSVを読み込み
特定の列に入っている文字数を半角40文字(全角なら20文字)を超える部分は
削除して、書き出す処理をしたい状況です。

今のコードでは、全角文字は20文字以内に収められました。
半角の英数文字の場合は、40文字まではカットしたくないのですが
そのような処理が実現できませんでした。

該当のソースコード

python

1df1 = pd.read_csv(input_file,encoding='cp932', dtype = 'object') 2 3#列名の再割り当て 4df1.columns = ['c01','c02','c03','c04'] 5 6# c02 を 20文字以内にする 7# 全角文字は問題ないが、半角文字も20文字になるため、余計にカットされてしまう。 8df1['c02'] = df1['c02'].str[:20] 9 10df1.to_csv(output_file, encoding='cp932',quoting=csv.QUOTE_ALL,index=False,header=None)

試したこと

内部の文字列のエンコードを変換してはどうかと考えましたが
Dataframeに対してencodeは出来ないようでした。

python

1df1['c02'] = df1['c02'].encode('utf-8').str[:20]

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

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

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

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

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

guest

回答2

0

ベストアンサー

unicodedata.east_asian_width を使用することで、全角か半角かの区別がつくようですので、これを利用して文字列の先頭を抜き出す関数を作ると良いかと思います。

かなりやっつけですがこんな感じ。

Python

1from unicodedata import east_asian_width 2 3def extract_first_part(s, limit_length=40): 4 total_length = 0 5 for i,c in enumerate(s): 6 length = 2 if east_asian_width(c) in list('WFA') else 1 7 total_length += length 8 if total_length > limit_length: 9 return s[:i] 10 return s

あとは Series.apply() 等を使って上記の関数を列に適用するだけでよいかと思います。

Python

1import pandas as pd 2 3df = pd.DataFrame({ 4 '文字列':['123456789012345678901234567890123456789012345123456789012345', 5 '123456789012345678901234567890', 6 '1234567890123456789012345678901234567890']}) 7 8print(df) 9# 文字列 10#0 123456789012345678901234567890123456789012345123456789012345 11#1 123456789012345678901234567890 12#2 1234567890123456789012345678901234567890 13 14df['文字列'] = df['文字列'].apply(extract_first_part) 15print(df) 16# 文字列 17#0 1234567890123456789012345678901234567890 18#1 12345678901234567890 19#2 1234567890123456789012345

投稿2019/04/09 00:03

magichan

総合スコア15898

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

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

hiroyuki828

2019/04/09 01:24

解決することができました。ありがとうございます。
guest

0

http://atasatamatara.hatenablog.jp/entry/2013/04/15/201955のような全角半角変換モジュールで変換してから処理を行ってはどうでしょうか?

投稿2019/04/08 14:36

nouken

総合スコア369

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

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

hiroyuki828

2019/04/09 01:29

ご回答ありがとうございました。 Dataframeに全角半角変換モジュールを当てることができなかったのと、 変換モジュールを使う場合、元のデータが変化してしまうので、変化せずに 処理が可能な回答の方をベストアンサーとさせていただきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問