Pandas 通过多个分隔符将一列拆分为同一列
Pandas Split a Column by Multiple delimiters into same column
我有一个 pandas 多列数据框。但感兴趣的专栏说的是 Col A,它看起来像:
dfInput
A
12 - ksjksu,nsusi,9018,1.00uy,9.0Vm,+/ - 20%(0.22suns); 891- 1o19jsksuisolslskosBN
205 - lksiosslsoujhs%ysus(0.33mismsn);31 - jsks,msnu
22 - 0204 - 2762.0uhsyuskis;14 - gnshj,msuis,lsolso2.2n; 67181 - iuwuwiwi
所以我的目标是将字符串分成两部分,一个是第一个 '-' before/after 分号,然后是其余部分,其中第一列将包含第一个 ' 左侧的所有数字-' 然后另一列将休息。所以我的输出数据框应该是这样的:
**dfOutDesired**
B C
12 891 ksjksu,nsusi,9018,1.00uy,9.0Vm,+/ - 20%(0.22suns) 1o19jsksuisolslskosBN
205 31 lksiosslsoujhs%ysus(0.33mismsn) jsks,msnu
22 14 67181 0204 - 2762.0uhsyuskis gnshj,msuis,lsolso2.2n iuwuwiwi
所以到目前为止,我已经根据我之前看到的帖子尝试了以下方法:
df['C'] = df["A"].str.replace(r'\w+\s*-\s*', '', regex=True)
df['A'] = df['A'].str.replace(' ', '')
df['A'] = df['A'].str.replace('-', ' - ')
df["B"] = df["A"].str.replace(r'\s*;\s*\S+;+\S+;+\s*', ' ', regex=True).str.strip()
所以我得到了 Col C 的部分正确输出(其中第三行的 0204 没有被拾取),但是对于 Col B,我得到了相同的 Col A,如下所示:
**mydfWrong**
B
12 - ksjksu,nsusi,9018,1.00uy,9.0Vm,+/ - 20%(0.22suns); 891- 1o19jsksuisolslskosBN
205 - lksiosslsoujhs%ysus(0.33mismsn);31 - jsks,msnu
22 - 0204 - 2762.0uhsyuskis;14 - gnshj,msuis,lsolso2.2n; 67181 - iuwuwiwi
C
ksjksu,nsusi,9018,1.00uy,9.0Vm,+/ - 20%(0.22suns) 1o19jsksuisolslskosBN
lksiosslsoujhs%ysus(0.33mismsn) jsks,msnu
2762.0uhsyuskis gnshj,msuis,lsolso2.2n iuwuwiwi
不确定在这种情况下如何正确使用正则表达式。因此,我们将不胜感激任何帮助。提前致谢。
您可以使用类似以下的方法来做到这一点。
get_nums
函数在 ;
上拆分,然后根据指定条件删除整数
get_the_rest
函数做相反的事情,用空格替换这些值
def get_nums(x):
return " ".join([re.search(r'^[0-9]+', y.strip()).group() for y in x.split(";")])
def get_the_rest(x):
return "".join([re.sub(r'[0-9]+\s?\-', '', y.strip()) for y in x.split(";")])
df["B"] = df["A"].apply(lambda x: get_nums(x))
df["C"] = df["A"].apply(lambda x: get_the_rest(x))
您可以使用单个正则表达式调用 findall
,然后只获取必要的数据:
import pandas as pd
df = pd.DataFrame({'A': ['205 - lksiosslsoujhs%ysus(0.33mismsn);31 - jsks,msnu', '22 - 0204 - 2762.0uhsyuskis;14 - gnshj,msuis,lsolso2.2n; 67181 - iuwuwiwi']})
rx = r'(\d+)\s*-\s*(.*?)(?=;\s*\d|$)' # Define the regex
m = df['A'].str.findall(rx) # Get all matches and captures
df["B"] = m.apply(lambda x: " ".join(c[0] for c in x)) # Join Group 1 values into Column B
df["C"] = m.apply(lambda x: " ".join(c[1] for c in x)) # Join Group 1 values into Column C
输出:
>>> print(df.to_string())
A B C
0 205 - lksiosslsoujhs%ysus(0.33mismsn);31 - jsks,msnu 205 31 lksiosslsoujhs%ysus(0.33mismsn) jsks,msnu
1 22 - 0204 - 2762.0uhsyuskis;14 - gnshj,msuis,lsolso2.2n; 67181 - iuwuwiwi 22 14 67181 0204 - 2762.0uhsyuskis gnshj,msuis,lsolso2.2n iuwuwiwi
查看匹配
的regex demo
(\d+)
- 第 1 组:一个或多个数字
\s*-\s*
- 包含零个或多个空格的 -
(.*?)
- 第 2 组:除换行字符外的任何零个或多个字符尽可能少
(?=;\s*\d|$)
- 匹配紧跟 ;
+ 零个或多个空格然后是数字或字符串结尾的位置的正向前瞻。
我有一个 pandas 多列数据框。但感兴趣的专栏说的是 Col A,它看起来像:
dfInput
A
12 - ksjksu,nsusi,9018,1.00uy,9.0Vm,+/ - 20%(0.22suns); 891- 1o19jsksuisolslskosBN
205 - lksiosslsoujhs%ysus(0.33mismsn);31 - jsks,msnu
22 - 0204 - 2762.0uhsyuskis;14 - gnshj,msuis,lsolso2.2n; 67181 - iuwuwiwi
所以我的目标是将字符串分成两部分,一个是第一个 '-' before/after 分号,然后是其余部分,其中第一列将包含第一个 ' 左侧的所有数字-' 然后另一列将休息。所以我的输出数据框应该是这样的:
**dfOutDesired**
B C
12 891 ksjksu,nsusi,9018,1.00uy,9.0Vm,+/ - 20%(0.22suns) 1o19jsksuisolslskosBN
205 31 lksiosslsoujhs%ysus(0.33mismsn) jsks,msnu
22 14 67181 0204 - 2762.0uhsyuskis gnshj,msuis,lsolso2.2n iuwuwiwi
所以到目前为止,我已经根据我之前看到的帖子尝试了以下方法:
df['C'] = df["A"].str.replace(r'\w+\s*-\s*', '', regex=True)
df['A'] = df['A'].str.replace(' ', '')
df['A'] = df['A'].str.replace('-', ' - ')
df["B"] = df["A"].str.replace(r'\s*;\s*\S+;+\S+;+\s*', ' ', regex=True).str.strip()
所以我得到了 Col C 的部分正确输出(其中第三行的 0204 没有被拾取),但是对于 Col B,我得到了相同的 Col A,如下所示:
**mydfWrong**
B
12 - ksjksu,nsusi,9018,1.00uy,9.0Vm,+/ - 20%(0.22suns); 891- 1o19jsksuisolslskosBN
205 - lksiosslsoujhs%ysus(0.33mismsn);31 - jsks,msnu
22 - 0204 - 2762.0uhsyuskis;14 - gnshj,msuis,lsolso2.2n; 67181 - iuwuwiwi
C
ksjksu,nsusi,9018,1.00uy,9.0Vm,+/ - 20%(0.22suns) 1o19jsksuisolslskosBN
lksiosslsoujhs%ysus(0.33mismsn) jsks,msnu
2762.0uhsyuskis gnshj,msuis,lsolso2.2n iuwuwiwi
不确定在这种情况下如何正确使用正则表达式。因此,我们将不胜感激任何帮助。提前致谢。
您可以使用类似以下的方法来做到这一点。
get_nums
函数在 ;
上拆分,然后根据指定条件删除整数
get_the_rest
函数做相反的事情,用空格替换这些值
def get_nums(x):
return " ".join([re.search(r'^[0-9]+', y.strip()).group() for y in x.split(";")])
def get_the_rest(x):
return "".join([re.sub(r'[0-9]+\s?\-', '', y.strip()) for y in x.split(";")])
df["B"] = df["A"].apply(lambda x: get_nums(x))
df["C"] = df["A"].apply(lambda x: get_the_rest(x))
您可以使用单个正则表达式调用 findall
,然后只获取必要的数据:
import pandas as pd
df = pd.DataFrame({'A': ['205 - lksiosslsoujhs%ysus(0.33mismsn);31 - jsks,msnu', '22 - 0204 - 2762.0uhsyuskis;14 - gnshj,msuis,lsolso2.2n; 67181 - iuwuwiwi']})
rx = r'(\d+)\s*-\s*(.*?)(?=;\s*\d|$)' # Define the regex
m = df['A'].str.findall(rx) # Get all matches and captures
df["B"] = m.apply(lambda x: " ".join(c[0] for c in x)) # Join Group 1 values into Column B
df["C"] = m.apply(lambda x: " ".join(c[1] for c in x)) # Join Group 1 values into Column C
输出:
>>> print(df.to_string())
A B C
0 205 - lksiosslsoujhs%ysus(0.33mismsn);31 - jsks,msnu 205 31 lksiosslsoujhs%ysus(0.33mismsn) jsks,msnu
1 22 - 0204 - 2762.0uhsyuskis;14 - gnshj,msuis,lsolso2.2n; 67181 - iuwuwiwi 22 14 67181 0204 - 2762.0uhsyuskis gnshj,msuis,lsolso2.2n iuwuwiwi
查看匹配
的regex demo(\d+)
- 第 1 组:一个或多个数字\s*-\s*
- 包含零个或多个空格的-
(.*?)
- 第 2 组:除换行字符外的任何零个或多个字符尽可能少(?=;\s*\d|$)
- 匹配紧跟;
+ 零个或多个空格然后是数字或字符串结尾的位置的正向前瞻。