文字列から句読点を取り除く最良の方法


638

次の方法よりも簡単な方法があるはずです。

import string
s = "string. With. Punctuation?" # Sample string 
out = s.translate(string.maketrans("",""), string.punctuation)

ある?


3
私にはかなり簡単に思えます。なぜ変更したいのですか?簡単にしたい場合は、関数で記述した内容をラップするだけです。
HannesOvrén、2008年

2
ええと、str.translateの副作用のようなものを使って仕事をしているのは、ちょっとハッカーっぽいようです。見逃した境界だけでなく、文字列全体を処理するstr.strip(chars)のようなものがあるのではないかと考えていました。
Lawrence Johnston、

2
データにも依存します。名前の一部にアンダースコアを含むサーバー名があるデータ(これはかなり一般的ないくつかの場所)でこれを使用することは悪いことです。データとそのデータが何であるかを理解していることを確認してください。そうしないと、最終的な問題のサブセットになる可能性があります。
EBGreen 2008年

54
また、句読点と呼ばれるものにも依存します。「The temperature in the O'Reilly & Arbuthnot-Smythe server's main rack is 40.5 degrees.」には、正確に1つの句読文字、2番目の「」が含まれています。
John Machin

37
string.punctuation英語以外の句読点がまったく含まれていないと言われている人がいないことに驚いています。、、!?:ד”〟などを考えています。
クレメント2013年

回答:


929

効率の観点から見ると、勝つことはできません

s.translate(None, string.punctuation)

Pythonの上位バージョンでは、次のコードを使用します。

s.translate(str.maketrans('', '', string.punctuation))

ルックアップテーブルを使用して、Cで生の文字列操作を実行しています。これに勝るものはありませんが、独自のCコードを記述します。

速度が問題にならない場合は、別の方法として次の方法があります。

exclude = set(string.punctuation)
s = ''.join(ch for ch in s if ch not in exclude)

これは、s.replaceを各文字で置き換えるよりも高速ですが、以下のタイミングからわかるように、正規表現やstring.translateなどの純粋でないpythonの手法ほどは機能しません。この種の問題の場合、それをできるだけ低いレベルで実行することで成果が得られます。

タイミングコード:

import re, string, timeit

s = "string. With. Punctuation"
exclude = set(string.punctuation)
table = string.maketrans("","")
regex = re.compile('[%s]' % re.escape(string.punctuation))

def test_set(s):
    return ''.join(ch for ch in s if ch not in exclude)

def test_re(s):  # From Vinko's solution, with fix.
    return regex.sub('', s)

def test_trans(s):
    return s.translate(table, string.punctuation)

def test_repl(s):  # From S.Lott's solution
    for c in string.punctuation:
        s=s.replace(c,"")
    return s

print "sets      :",timeit.Timer('f(s)', 'from __main__ import s,test_set as f').timeit(1000000)
print "regex     :",timeit.Timer('f(s)', 'from __main__ import s,test_re as f').timeit(1000000)
print "translate :",timeit.Timer('f(s)', 'from __main__ import s,test_trans as f').timeit(1000000)
print "replace   :",timeit.Timer('f(s)', 'from __main__ import s,test_repl as f').timeit(1000000)

これにより、次の結果が得られます。

sets      : 19.8566138744
regex     : 6.86155414581
translate : 2.12455511093
replace   : 28.4436721802

27
タイミング情報のおかげで、私はそのようなことを自分で行うことを考えていましたが、あなたが書いたものは私がやったことよりも優れており、これから、これから書くタイミングコードのテンプレートとして使用できます。
ローレンスジョンストン

29
すばらしい答えです。テーブルを削除することで簡単にできます。ドキュメントは言う:(「のみ削除文字変換のためになしにテーブル引数を設定する」docs.python.org/library/stdtypes.html#str.translate
アレクサンドロスマリノス

3
また、translate()の動作はstrオブジェクトとunicodeオブジェクトで異なるため、常に同じデータ型で作業していることを確認する必要がありますが、この回答のアプローチは両方に同じように機能するため、便利です。
Richard J

36
Python3では、 ?table = string.maketrans("","")に置き換える必要がありtable = str.maketrans({key: None for key in string.punctuation})ます。
SparkAndShine 2016年

19
議論を更新することは、Python 3.6の時点でregex最も効率的な方法です。変換よりもほぼ2倍高速です。また、セットと置換はそれほど悪くありません!どちらも4倍以上改善されています:)
Ryan Soklaski 2017

143

正規表現は、ご存知であれば簡単です。

import re
s = "string. With. Punctuation?"
s = re.sub(r'[^\w\s]','',s)

4
@外れ値の説明:(^)ではない単語の文字またはスペースを空の文字列に置き換えます。ただし、\ wは通常、アンダースコアにも一致します。
Matthias

4
@SIslam unicodeフラグが設定されたunicodeで機能すると思いますs = re.sub(r'[^\w\s]','',s, re.UNICODE)。Linuxのpython 3でテストすると、タミル語の文字を使用したフラグなしでも動作しますதமிழ்。
Matthias

@Matthias MacでPython 3.6.5を使用してコードを試しましたが、タミル語の文字出力は少し異なり、入力தமிழ்はதமிழ்になります。タミル語については知りませんが、それが予想されるかどうかはわかりません。
shiouming

71

使用の便宜上、Python 2とPython 3の両方で文字列から句読点を削除するメモをまとめます。詳細な説明については、他の回答を参照してください。


Python 2

import string

s = "string. With. Punctuation?"
table = string.maketrans("","")
new_s = s.translate(table, string.punctuation)      # Output: string without punctuation

Python 3

import string

s = "string. With. Punctuation?"
table = str.maketrans(dict.fromkeys(string.punctuation))  # OR {key: None for key in string.punctuation}
new_s = s.translate(table)                          # Output: string without punctuation

51
myString.translate(None, string.punctuation)

4
ああ、私はこれを試しましたが、すべての場合でうまくいくわけではありません。myString.translate(string.maketrans( ""、 "")、string.punctuation)は正常に機能します。
Aidan Kane

12
以下のためにという注意strのPython 3であり、unicodePythonの2で、deletechars引数がサポートされていません。
agf

4
myString.translate(string.maketrans( ""、 "")、string.punctuation)は、ユニコード文字列では機能しません(難しい方法が見つかりました)
Marc Maxmeister

44
TypeError: translate() takes exactly one argument (2 given):(
ブライアンTingle

3
@BrianTingle:私のコメントのPython 3コードを見てください(1つの引数を渡します)。リンクをクリックして、Unicodeで動作するPython 2コードそのPython 3の適応
jfs

29

私は通常、次のようなものを使用します。

>>> s = "string. With. Punctuation?" # Sample string
>>> import string
>>> for c in string.punctuation:
...     s= s.replace(c,"")
...
>>> s
'string With Punctuation'

2
醜いワンライナー:reduce(lambda s,c: s.replace(c, ''), string.punctuation, s)
jfs 2012

1
すばらしいですが、長いハイフンなどの一部の句読点は削除されません
ウラジミールスタジロフ

25

string.punctuationASCII のみです!より正確な(しかし非常に遅い)方法は、unicodedataモジュールを使用することです。

# -*- coding: utf-8 -*-
from unicodedata import category
s = u'String — with -  «punctation »...'
s = ''.join(ch for ch in s if category(ch)[0] != 'P')
print 'stripped', s

他のタイプの文字も一般化して取り除くことができます。

''.join(ch for ch in s if category(ch)[0] not in 'SP')

また~*+§$、自分の視点に応じて「句読点」の場合とそうでない場合のある文字を削除します。


3
次のことができますregex.sub(ur"\p{P}+", "", text)
。– jfs

残念ながら、など~は句読点のカテゴリの一部ではありません。また、シンボルカテゴリもテストする必要があります。
CJジャクソン

24

reファミリに精通している場合は、必ずしも単純ではありませんが、別の方法です。

import re, string
s = "string. With. Punctuation?" # Sample string 
out = re.sub('[%s]' % re.escape(string.punctuation), '', s)

1
string.punctuationのシーケンスは、-であるため機能します。適切、昇順、ギャップなし、ASCII順。Pythonにはこの権利がありますが、string.punctuationのサブセットを使用しようとすると、驚きの "-"が発生するため、これがショーストッパーになる可能性があります。
S.Lott、2008年

2
実際、それはまだ間違っています。シーケンス "\]"はエスケープとして扱われますが(偶然に]が閉じないため、別のエラーがバイパスされます)、\はエスケープされません。これを防ぐには、re.escape(string.punctuation)を使用する必要があります。
ブライアン、

1
はい、例を単純にするために機能したので省略しましたが、組み込む必要があるのは当然です。
Vinko Vrsalovic 2008年

13

Python 3 strまたはPython 2のunicode値の場合、str.translate()辞書のみを受け取ります。コードポイント(整数)はそのマッピングで検索され、マッピングされたものNoneはすべて削除されます。

次に(いくつかの)句読点を削除するには、次を使用します。

import string

remove_punct_map = dict.fromkeys(map(ord, string.punctuation))
s.translate(remove_punct_map)

dict.fromkeys()クラスメソッドは、それは些細にすべての値を設定し、マッピングを作成することができNone、キーの配列に基づきます。

ASCII句読点だけでなく、すべての句読点を削除するには、テーブルを少し大きくする必要があります。JF Sebastianの回答(Python 3バージョン)を参照してください。

import unicodedata
import sys

remove_punct_map = dict.fromkeys(i for i in range(sys.maxunicode)
                                 if unicodedata.category(chr(i)).startswith('P'))

Unicodeをサポートするstring.punctuationだけでは不十分です。私の回答を
jfs

@JFSebastian:確かに、私の回答はトップ投票の文字と同じ文字を使用するだけでした。テーブルのPython 3バージョンを追加しました。
Martijn Pieters

上位投票の回答はASCII文字列に対してのみ機能します。あなたの答えは明示的にUnicodeサポートを主張しています。
jfs

1
@JFSebastian:Unicode文字列に対して機能します。ASCII句読点を取り除きます。句読点がすべて取り除かれているとは私は主張していません。:-)ポイントは、unicodeオブジェクト対Python 2 strオブジェクトの正しい手法を提供することでした。
Martijn Pieters

12

string.punctuation現実の世界で一般的に使用される句読点の負荷を逃します。ASCII以外の句読点で機能するソリューションはどうですか?

import regex
s = u"string. With. Some・Really Weird、Non?ASCII。 「(Punctuation)」?"
remove = regex.compile(ur'[\p{C}|\p{M}|\p{P}|\p{S}|\p{Z}]+', regex.UNICODE)
remove.sub(u" ", s).strip()

個人的には、これがPythonの文字列から句読点を削除する最良の方法だと思います。

  • すべてのUnicode句読点を削除します
  • これは簡単に変更できます。たとえば\{S}、句読点を削除したい場合はを削除できますが、記号はのままにしておきます$
  • 保持したいものと削除したいものを本当に具体的にすることができます\{Pd}。たとえば、ダッシュだけが削除されます。
  • この正規表現は空白も正規化します。タブ、キャリッジリターン、その他の奇妙な要素を1つのスペースにマッピングします。

これは、ウィキペディアで詳細を読むことができる Unicode文字プロパティを使用します。


9

この答えはまだ見ていません。ただ正規表現を使用してください。単語文字(\w)と数字()のほかに\d空白文字(\s)が続く文字をすべて削除します。

import re
s = "string. With. Punctuation?" # Sample string 
out = re.sub(ur'[^\w\d\s]+', '', s)

1
\dのサブセットであるため、冗長です\w
1

数字文字はWord文字のサブセットと見なされますか?Wordの文字は、a-zA-Zなど、実際の単語を構成できる文字だと思いましたか?
Blairg23、19年

はい、正規表現の「単語」にはアルファベット、数字、アンダースコアが含まれます。\wドキュメントの説明を参照してください:docs.python.org/3/library/re.html
blhsing

8

Python 3.5のワンライナーは次のとおりです。

import string
"l*ots! o(f. p@u)n[c}t]u[a'ti\"on#$^?/".translate(str.maketrans({a:None for a in string.punctuation}))

7

これは最善の解決策ではないかもしれませんが、これは私がやった方法です。

import string
f = lambda x: ''.join([i for i in x if i not in string.punctuation])

6

これが私が書いた関数です。あまり効率的ではありませんが、簡単で、必要な句読点を追加または削除できます。

def stripPunc(wordList):
    """Strips punctuation from list of words"""
    puncList = [".",";",":","!","?","/","\\",",","#","@","$","&",")","(","\""]
    for punc in puncList:
        for word in wordList:
            wordList=[word.replace(punc,'') for word in wordList]
    return wordList

5
import re
s = "string. With. Punctuation?" # Sample string 
out = re.sub(r'[^a-zA-Z0-9\s]', '', s)

それはASCII文字に対してのみ機能するようです。
-avirr

5

更新と同様に、@ Brianの例をPython 3で書き直して、正規表現のコンパイル手順を関数内に移動するように変更しました。ここでの私の考えは、関数を機能させるために必要なすべてのステップの時間を計ることでした。おそらく、分散コンピューティングを使用していて、ワーカー間で共有する正規表現オブジェクトを使用できず、ワーカーre.compileごとにステップを踏む必要がある場合があります。また、Python 3のmaketransの2つの異なる実装の時間を知りたいと思っていました。

table = str.maketrans({key: None for key in string.punctuation})

table = str.maketrans('', '', string.punctuation)

さらに、setを使用する別の方法を追加しました。ここでは、交差関数を利用して反復回数を減らしています。

これは完全なコードです:

import re, string, timeit

s = "string. With. Punctuation"


def test_set(s):
    exclude = set(string.punctuation)
    return ''.join(ch for ch in s if ch not in exclude)


def test_set2(s):
    _punctuation = set(string.punctuation)
    for punct in set(s).intersection(_punctuation):
        s = s.replace(punct, ' ')
    return ' '.join(s.split())


def test_re(s):  # From Vinko's solution, with fix.
    regex = re.compile('[%s]' % re.escape(string.punctuation))
    return regex.sub('', s)


def test_trans(s):
    table = str.maketrans({key: None for key in string.punctuation})
    return s.translate(table)


def test_trans2(s):
    table = str.maketrans('', '', string.punctuation)
    return(s.translate(table))


def test_repl(s):  # From S.Lott's solution
    for c in string.punctuation:
        s=s.replace(c,"")
    return s


print("sets      :",timeit.Timer('f(s)', 'from __main__ import s,test_set as f').timeit(1000000))
print("sets2      :",timeit.Timer('f(s)', 'from __main__ import s,test_set2 as f').timeit(1000000))
print("regex     :",timeit.Timer('f(s)', 'from __main__ import s,test_re as f').timeit(1000000))
print("translate :",timeit.Timer('f(s)', 'from __main__ import s,test_trans as f').timeit(1000000))
print("translate2 :",timeit.Timer('f(s)', 'from __main__ import s,test_trans2 as f').timeit(1000000))
print("replace   :",timeit.Timer('f(s)', 'from __main__ import s,test_repl as f').timeit(1000000))

これは私の結果です:

sets      : 3.1830138750374317
sets2      : 2.189873124472797
regex     : 7.142953420989215
translate : 4.243278483860195
translate2 : 2.427158243022859
replace   : 4.579746678471565

4
>>> s = "string. With. Punctuation?"
>>> s = re.sub(r'[^\w\s]','',s)
>>> re.split(r'\s*', s)


['string', 'With', 'Punctuation']

2
詳細を編集してください。コードのみの回答と「これを試す」の回答は、検索可能なコンテンツが含まれておらず、誰かが「これを試す」必要がある理由を説明していないため、お勧めしません。
パリトッシュ2016

4

これが正規表現なしのソリューションです。

import string

input_text = "!where??and!!or$$then:)"
punctuation_replacer = string.maketrans(string.punctuation, ' '*len(string.punctuation))    
print ' '.join(input_text.translate(punctuation_replacer).split()).strip()

Output>> where and or then
  • 句読点をスペースに置き換えます
  • 単語間の複数のスペースを1つのスペースに置き換える
  • 末尾のスペースがある場合は削除します(strip()を使用)

4

ワンライナーはそれほど厳密ではない場合に役立つかもしれません:

''.join([c for c in s if c.isalnum() or c.isspace()])

2
#FIRST METHOD
#Storing all punctuations in a variable    
punctuation='!?,.:;"\')(_-'
newstring='' #Creating empty string
word=raw_input("Enter string: ")
for i in word:
     if(i not in punctuation):
                  newstring+=i
print "The string without punctuation is",newstring

#SECOND METHOD
word=raw_input("Enter string: ")
punctuation='!?,.:;"\')(_-'
newstring=word.translate(None,punctuation)
print "The string without punctuation is",newstring


#Output for both methods
Enter string: hello! welcome -to_python(programming.language)??,
The string without punctuation is: hello welcome topythonprogramminglanguage

2
with open('one.txt','r')as myFile:

    str1=myFile.read()

    print(str1)


    punctuation = ['(', ')', '?', ':', ';', ',', '.', '!', '/', '"', "'"] 

for i in punctuation:

        str1 = str1.replace(i," ") 
        myList=[]
        myList.extend(str1.split(" "))
print (str1) 
for i in myList:

    print(i,end='\n')
    print ("____________")

0

なぜあなたは誰もこれを使わないのですか?

 ''.join(filter(str.isalnum, s)) 

遅すぎる?


これによりスペースも削除されることに注意してください。
Georgy

0

ユニコードを検討しています。python3でチェックされたコード。

from unicodedata import category
text = 'hi, how are you?'
text_without_punc = ''.join(ch for ch in text if not category(ch).startswith('P'))

-1

Pythonを使用してストップワードをテキストファイルから削除する

print('====THIS IS HOW TO REMOVE STOP WORS====')

with open('one.txt','r')as myFile:

    str1=myFile.read()

    stop_words ="not", "is", "it", "By","between","This","By","A","when","And","up","Then","was","by","It","If","can","an","he","This","or","And","a","i","it","am","at","on","in","of","to","is","so","too","my","the","and","but","are","very","here","even","from","them","then","than","this","that","though","be","But","these"

    myList=[]

    myList.extend(str1.split(" "))

    for i in myList:

        if i not in stop_words:

            print ("____________")

            print(i,end='\n')

-2

私はこのような関数を使いたいです:

def scrub(abc):
    while abc[-1] is in list(string.punctuation):
        abc=abc[:-1]
    while abc[0] is in list(string.punctuation):
        abc=abc[1:]
    return abc

1
これは最初と最後から文字を取り除いています。abc.strip(string.punctuation)代わりに使用してください。途中でそのような文字削除されることはありません。
Martijn Pieters
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.