문자열 길이에 따라 문자열 데이터 필터링
저는 문자열 길이가 10이 아닌 데이터를 걸러내는 것을 좋아합니다.
열이 있는 행을 걸러내려고 하면A
의 또는B
이거는 줄 길이가 10이 아니라 해봤어요.
df=pd.read_csv('filex.csv')
df.A=df.A.apply(lambda x: x if len(x)== 10 else np.nan)
df.B=df.B.apply(lambda x: x if len(x)== 10 else np.nan)
df=df.dropna(subset=['A','B'], how='any')
이것은 느리게 작동하지만 작동합니다.
그러나 데이터를 저장할 때 오류가 발생하기도 합니다.A
는 문자열이 아니라 숫자입니다(다음의 경우 숫자로 interpre됨).read_csv
입력 파일 읽기):
File "<stdin>", line 1, in <lambda>
TypeError: object of type 'float' has no len()
저는 이것 대신에 좀 더 효율적이고 우아한 코드가 있어야 한다고 생각합니다.
아래의 답변과 의견을 토대로 제가 찾은 가장 간단한 해결책은 다음과 같습니다.
df=df[df.A.apply(lambda x: len(str(x))==10]
df=df[df.B.apply(lambda x: len(str(x))==10]
아니면
df=df[(df.A.apply(lambda x: len(str(x))==10) & (df.B.apply(lambda x: len(str(x))==10)]
아니면
df=df[(df.A.astype(str).str.len()==10) & (df.B.astype(str).str.len()==10)]
import pandas as pd
df = pd.read_csv('filex.csv')
df['A'] = df['A'].astype('str')
df['B'] = df['B'].astype('str')
mask = (df['A'].str.len() == 10) & (df['B'].str.len() == 10)
df = df.loc[mask]
print(df)
filex.csv에 적용됨:
A,B
123,abc
1234,abcd
1234567890,abcdefghij
인쇄물 위의 암호
A B
2 1234567890 abcdefghij
다른 열의 주어진 조건과 그 값을 기반으로 행을 필터링하는 더 피톤적인 방법:
가정하에df
다음 중:
data = {
"names": ["Alice", "Zac", "Anna", "O"],
"cars": ["Civic", "BMW", "Mitsubishi", "Benz"],
"age": ["1", "4", "2", "0"],
}
df=pd.DataFrame(data)
df:
age cars names
0 1 Civic Alice
1 4 BMW Zac
2 2 Mitsubishi Anna
3 0 Benz O
그러면:
df[
df["names"].apply(lambda x: len(x) > 1)
& df["cars"].apply(lambda x: "i" in x)
& df["age"].apply(lambda x: int(x) < 2)
]
우리는 다음을 가질 것입니다.
age cars names
0 1 Civic Alice
위의 조건에서 우리는 먼저 문자열의 길이를 살펴본 다음, 편지가 있는지 확인합니다."i"
문자열에 존재하는지 여부를 확인합니다. 마지막으로 첫 번째 열의 정수 값을 확인합니다.
저는 개인적으로 이 방법이 가장 쉽다는 것을 알았습니다.
df['column_name'] = df[df['column_name'].str.len()!=10]
다음을 사용할 수도 있습니다.
df.query('A.str.len() == 10 & B.str.len() == 10')
이와 같은 문자열 연산의 경우, 내장된 방법(람다 없음)을 사용하는 바닐라 파이썬은 다음보다 훨씬 빠릅니다.apply()
아니면str.len()
.
매핑을 통해 부울 마스크 구축len
목록 내의 각 문자열에 대한 이해는 약 40-70% 빠릅니다.apply()
그리고.str.len()
각각 다음과 같다.
다중 열의 경우zip()
다른 열의 값을 동시에 평가할 수 있습니다.
col_A_len = map(len, df['A'].astype(str))
col_B_len = map(len, df['B'].astype(str))
m = [a==3 and b==3 for a,b in zip(col_A_len, col_B_len)]
df1 = df[m]
단일 열의 경우 드롭zip()
그리고 기둥 위를 빙빙 돌면서 길이가 3과 같은지 확인합니다.
df2 = df[[a==3 for a in map(len, df['A'].astype(str))]]
이 코드는 약간 간결하게 작성될 수 있습니다.Series.map()
방법(그러나 팬더 오버헤드로 인해 목록 이해보다 약간 느림):
df2 = df[df['A'].astype(str).map(len)==3]
행에 숫자가 있으면 숫자가 부동소수자로 변환됩니다.
cvs에서 가져온 후 모든 행을 문자열로 변환합니다.성능 향상을 위해 람다를 여러 스레드로 분할할 수 있습니다.
사용가능df.apply(len)
. 그것은 당신에게 결과를 줄 것입니다.
열 A 및 B에서 길이 10 이외의 값을 필터링하고, 여기서는 lambda 식을 map() 함수로 전달합니다. map() 함수는 Series Object에서 항상 적용됩니다.
df = df[df['A'].map(lambda x: len(str(x)) == 10)]
df = df[df['B'].map(lambda x: len(str(x)) == 10)]
applymap을 사용하여 원하는 모든 열을 한 번에 필터링한 다음 .all() 메서드를 사용하여 두 열이 모두 참인 행만 필터링할 수 있습니다.
#The *mask* variable is a dataframe of booleans, giving you True or False for the selected condition
mask = df[['A','B']].applymap(lambda x: len(str(x)) == 10)
#Here you can just use the mask to filter your rows, using the method *.all()* to filter only rows that are all True, but you could also use the *.any()* method for other needs
df = df[mask.all(axis=1)]
언급URL : https://stackoverflow.com/questions/19937362/filter-string-data-based-on-its-string-length
'programing' 카테고리의 다른 글
생성된 XML에서 'standalone="yes" 제거 (0) | 2023.09.20 |
---|---|
대용량 파일을 처리할 수 있는 Lightweight XML Viewer (0) | 2023.09.20 |
asp.net mvc 4에서 jquery ajax 호출 후 서버측 리디렉션 (0) | 2023.09.20 |
Swift 기본 AlertViewController 제약 조건 위반 (0) | 2023.09.20 |
jQuery 또는 pure JS를 사용하여 모든 체크박스를 리셋하는 방법? (0) | 2023.09.20 |