열의 문자열에서 불필요한 부분 제거
Data Frame 열의 문자열에서 불필요한 부분을 제거하는 효율적인 방법을 찾고 있습니다.
데이터는 다음과 같습니다.
time result
1 09:00 +52A
2 10:00 +62B
3 11:00 +44a
4 12:00 +30b
5 13:00 -110a
다음 목적으로 데이터를 잘라야 합니다.
time result
1 09:00 52
2 10:00 62
3 11:00 44
4 12:00 30
5 13:00 110
는 는 i i는노노 i i i i i..str.lstrip('+-')
str.rstrip('aAbBcC')
TypeError: wrapper() takes exactly 1 argument (2 given)
어떤 조언이라도 해주면 정말 감사합니다!
data['result'] = data['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC'))
열의 문자열에서 불필요한 부분을 제거하려면 어떻게 해야 합니까?
원래 질문이 게시된 지 6년이 지난 지금, 판다들은 이러한 현악기 조작을 간결하게 수행할 수 있는 많은 "사상화된" 현악기 기능을 가지고 있다.
이 답변에서는 이러한 문자열 함수 중 몇 가지를 살펴보고 더 빠른 대안을 제안하며 마지막에 타이밍 비교를 진행합니다.
.str.replace
일치시킬 서브스트링/패턴 및 이 서브스트링을 대체할 서브스트링을 대체할 서브스트링을 지정합니다.
pd.__version__
# '0.24.1'
df
time result
1 09:00 +52A
2 10:00 +62B
3 11:00 +44a
4 12:00 +30b
5 13:00 -110a
df['result'] = df['result'].str.replace(r'\D', '')
df
time result
1 09:00 52
2 10:00 62
3 11:00 44
4 12:00 30
5 13:00 110
결과를 정수로 변환해야 할 경우 를 사용할 수 있습니다.
df['result'] = df['result'].str.replace(r'\D', '').astype(int)
df.dtypes
time object
result int64
dtype: object
」의 변경을 df
in-place 를 사용합니다.
df2 = df.assign(result=df['result'].str.replace(r'\D', ''))
df
# Unchanged
.str.extract
유지할 서브스트링을 추출할 때 편리합니다.
df['result'] = df['result'].str.extract(r'(\d+)', expand=False)
df
time result
1 09:00 52
2 10:00 62
3 11:00 44
4 12:00 30
5 13:00 110
★★★★★★★★★★★★★★★★ extract
캡처 그룹을 하나 이상 지정해야 합니다. expand=False
는 첫 번째 캡처 그룹에서 캡처한 항목이 포함된 시리즈를 반환합니다.
.str.split
그리고
분할은 모든 문자열이 이 일관된 구조를 따른다고 가정할 때 작동합니다.
# df['result'] = df['result'].str.split(r'\D').str[1]
df['result'] = df['result'].str.split(r'\D').str.get(1)
df
time result
1 09:00 52
2 10:00 62
3 11:00 44
4 12:00 30
5 13:00 110
일반적인 솔루션을 찾고 있다면 권장하지 마십시오.
쉬운 내용이 에
str
위의 악세사리 기반 솔루션은 여기서 정지할 수 있습니다.그러나 더 빠르고 더 성능이 뛰어난 대체 방법에 관심이 있는 경우 계속 읽어 보십시오.
최적화: 목록 통합
일부 상황에서는 팬더 스트링 기능보다 목록 수집이 선호될 수 있습니다.그 이유는 문자열 함수는 본래 벡터화(진정한 의미)가 어렵기 때문에 대부분의 문자열 및 regex 함수는 오버헤드가 높은 루프 주위의 래퍼일 뿐입니다.
팬더에 대한 포루프(for lo-loops in panda? "내가 언제 신경써야 할까?"라고 더 자세히 말한다.
str.replace
쓸 수.re.sub
import re
# Pre-compile your regex pattern for more performance.
p = re.compile(r'\D')
df['result'] = [p.sub('', x) for x in df['result']]
df
time result
1 09:00 52
2 10:00 62
3 11:00 44
4 12:00 30
5 13:00 110
str.extract
는 목록 쓸 수.re.search
,
p = re.compile(r'\d+')
df['result'] = [p.search(x)[0] for x in df['result']]
df
time result
1 09:00 52
2 10:00 62
3 11:00 44
4 12:00 30
5 13:00 110
NaN 또는 일치하지 않을 가능성이 있는 경우 오류 체크를 포함하기 위해 위의 내용을 다시 작성해야 합니다.저는 함수를 사용해서 합니다.
def try_extract(pattern, string):
try:
m = pattern.search(string)
return m.group(0)
except (TypeError, ValueError, AttributeError):
return np.nan
p = re.compile(r'\d+')
df['result'] = [try_extract(p, x) for x in df['result']]
df
time result
1 09:00 52
2 10:00 62
3 11:00 44
4 12:00 30
5 13:00 110
리스트의 내용을 정리하여 @eumiro와 @MonkeyButter의 답변을 다시 쓸 수도 있습니다.
df['result'] = [x.lstrip('+-').rstrip('aAbBcC') for x in df['result']]
그리고.
df['result'] = [x[1:-1] for x in df['result']]
NaN 등의 취급에 대해서도 같은 규칙이 적용된다.
퍼포먼스 비교
성능도를 사용하여 생성된 그래프입니다.참고로 전체 코드 목록입니다.관련 기능은 다음과 같습니다.
이러한 비교 중 일부는 OP의 데이터 구조를 이용하기 때문에 불공정하지만 원하는 것을 이용합니다.한 가지 주의할 점은 모든 목록 이해 기능이 동등한 판다 변종보다 빠르거나 유사하다는 것입니다.
기능들
def eumiro(df): return df.assign( result=df['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC'))) def coder375(df): return df.assign( result=df['result'].replace(r'\D', r'', regex=True)) def monkeybutter(df): return df.assign(result=df['result'].map(lambda x: x[1:-1])) def wes(df): return df.assign(result=df['result'].str.lstrip('+-').str.rstrip('aAbBcC')) def cs1(df): return df.assign(result=df['result'].str.replace(r'\D', '')) def cs2_ted(df): # `str.extract` based solution, similar to @Ted Petrou's. so timing together. return df.assign(result=df['result'].str.extract(r'(\d+)', expand=False)) def cs1_listcomp(df): return df.assign(result=[p1.sub('', x) for x in df['result']]) def cs2_listcomp(df): return df.assign(result=[p2.search(x)[0] for x in df['result']]) def cs_eumiro_listcomp(df): return df.assign( result=[x.lstrip('+-').rstrip('aAbBcC') for x in df['result']]) def cs_mb_listcomp(df): return df.assign(result=[x[1:-1] for x in df['result']])
팬더 치환기능을 사용할 수 있습니다.심플하고 파워풀한 regex를 사용할 수 있습니다.아래에서는 regex\D를 사용하여 숫자가 아닌 문자를 삭제합니다.하지만 regex를 사용하면 상당히 창의적일 수 있습니다.
data['result'].replace(regex=True,inplace=True,to_replace=r'\D',value=r'')
데이터 프레임 열에서 제거할 위치 수를 알고 있는 경우에는 람다 함수 내에서 문자열 인덱싱을 사용하여 해당 부분을 제거할 수 있습니다.
마지막 문자:
data['result'] = data['result'].map(lambda x: str(x)[:-1])
처음 두 글자:
data['result'] = data['result'].map(lambda x: str(x)[2:])
여기에 오류가 있습니다. 현재 다음 항목에 인수를 전달할 수 없습니다.str.lstrip
그리고.str.rstrip
:
http://github.com/pydata/pandas/issues/2411
편집: 2012-12-07 개발 브랜치에서는 다음과 같이 동작합니다.
In [8]: df['result'].str.lstrip('+-').str.rstrip('aAbBcC')
Out[8]:
1 52
2 62
3 44
4 30
5 110
Name: result
매우 간단한 방법은 다음과 같습니다.extract
method를 사용하여 모든 숫자를 선택합니다.정규 표현만 제공하면 됩니다.'\d+'
임의의 자리수를 추출합니다.
df['result'] = df.result.str.extract(r'(\d+)', expand=True).astype(int)
df
time result
1 09:00 52
2 10:00 62
3 11:00 44
4 12:00 30
5 13:00 110
DF에도 숫자 사이에 추가 문자가 있다고 가정합니다.마지막 엔트리
result time
0 +52A 09:00
1 +62B 10:00
2 +44a 11:00
3 +30b 12:00
4 -110a 13:00
5 3+b0 14:00
str.replace를 사용하여 시작과 끝뿐만 아니라 중간 문자도 제거할 수 있습니다.
DF['result'] = DF['result'].str.replace('\+|a|b|\-|A|B', '')
출력:
result time
0 52 09:00
1 62 10:00
2 44 11:00
3 30 12:00
4 110 13:00
5 30 14:00
이러한 유형의 작업은 속도가 더 빠르기 때문에 목록 수집을 자주 사용합니다.
이와 같은 작업을 수행하는 다양한 방법(즉, DataFrame 내 시리즈의 모든 요소를 수정하는 방법) 간에 성능 면에서 큰 차이가 있을 수 있습니다.대부분의 경우 목록 이해가 가장 빠릅니다. 이 작업은 아래 코드 레이스를 참조하십시오.
import pandas as pd
#Map
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']})
%timeit data['result'] = data['result'].map(lambda x: x.lstrip('+-').rstrip('aAbBcC'))
10000 loops, best of 3: 187 µs per loop
#List comprehension
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']})
%timeit data['result'] = [x.lstrip('+-').rstrip('aAbBcC') for x in data['result']]
10000 loops, best of 3: 117 µs per loop
#.str
data = pd.DataFrame({'time':['09:00','10:00','11:00','12:00','13:00'], 'result':['+52A','+62B','+44a','+30b','-110a']})
%timeit data['result'] = data['result'].str.lstrip('+-').str.rstrip('aAbBcC')
1000 loops, best of 3: 336 µs per loop
정규식을 사용하여 다음을 시도해 보십시오.
import re
data['result'] = data['result'].map(lambda x: re.sub('[-+A-Za-z]',x)
"str.replace"를 사용하는 것이 람다보다 빠르며 데이터 치수가 클 때 매핑합니다.
your_data["result"]=your_data["result"].str.replace("+","")
your_data["result"]=your_data["result"].str.replace("-","")
언급URL : https://stackoverflow.com/questions/13682044/remove-unwanted-parts-from-strings-in-a-column
'sourcecode' 카테고리의 다른 글
MariaDB에서 CONCAT()와 WHERE를 결합하는 방법 (0) | 2022.11.27 |
---|---|
vuejs에서 http referre를 얻는 방법 (0) | 2022.11.27 |
독트린 하이드레이션이 뭐죠? (0) | 2022.11.27 |
null이 PHP의 한 줄에 다른 변수를 사용하는 경우 (0) | 2022.11.27 |
larabel 5.x에서는 많은 수와 속한 수의 비교 (0) | 2022.11.27 |