在单个Pandas数据框列中将字符串与数字分开,并创建两个新列

5

我很惊讶之前没有人在SO上问过这个问题,因为它看起来是一个足够简单的问题。

我有一个pandas数据框中的单列,看起来像这样:

df = pd.DataFrame(data=[['APPLEGATE WINERY    455.292049'],['AMAND FARM  849.827192'],['COBB FARM ST    1039.49357'],['DIRIGIA 2048.947284']], columns = ['Col1'])

    Col1
0   APPLEGATE WINERY 455.292049
1   AMAND FARM 849.827192
2   COBB FARM ST 1039.49357
3   DIRIGIA 2048.947284

我只想将字符串字符与数字分开,因此结果应该是这样的。

Name                Area
APPLEGATE WINERY    455.292049
AMAND FARM          849.827192
COBB FARM ST        1039.49357
DIRIGIA             2048.947284

我知道在Python中可以使用正则表达式,但这似乎有些过度,因为a)它只是数据类型的分离,b)字符串长度不同,数字位数也不相同。
那么一个结果会开始看起来像这样:
df['Name'] = df.Col1.str.extract('([A-Z]\w{0,})', expand=True)
df['Area'] = df.Col1.str.extract('(\d)', expand=True)

但是有没有一个好的、干净的解决方案来解决这个问题,而不必费事使用正则表达式,而是将字符串和数字分开成两列呢?


你可能有一个 32nd Street 吗? - user3483203
所有的名称都必须以字母开头,不能是数字。 - JAG2024
4个回答

7

使用单个extract调用。如果您使用此正则表达式,则还需要从结果中删除尾随空格。

df2 = (df['Col1'].str.extract(r'(?P<Name>.*?)(?P<Area>\d+(?:\.\d+)?)')
                 .applymap(str.strip))
df2
               Name         Area
0  APPLEGATE WINERY   455.292049
1        AMAND FARM   849.827192
2      COBB FARM ST   1039.49357
3           DIRIGIA  2048.947284

正则表达式剖析

(?P<Name>   # first named capture group - "Name"
    .*?     # match anything (non-greedy)
)
(?P<Area>   # second named group - "Area"
    \d+     # match one or more digits,
    (?:     
       \.   # decimal
       \d+  # trailing digits
    )?      # the `?` indicates floating point is optional
)

PS,将“Area”列转换为数字,请使用pd.to_numeric

注:pd是指Pandas库,用于数据分析和处理。

2
我非常感谢正则表达式的解释!非常感谢。为了使这个解决方案工作,我还必须将数据框转换为字符串.astype(str),因为我之前遇到了错误Can only use .str accessor with string values, which use np.object_ dtype in pandas,但现在它可以工作了。 - JAG2024
1
@JAG2024 不用客气。正则表达式背后的思路是找到类似浮点数的东西,并将其作为第二组“面积”捕获,然后将其之前的所有内容捕获为“名称”。很高兴它有用。 - cs95

2
感觉你只需要使用 str.rsplit。最初的回答。
df.Col1.str.rsplit(' ',1,expand=True).apply(lambda x : x.str.strip(),1)
Out[314]: 
                  0            1
0  APPLEGATE WINERY   455.292049
1        AMAND FARM   849.827192
2      COBB FARM ST   1039.49357
3           DIRIGIA  2048.947284

假设该列中没有尾随空格,这是一个不错的解决方案。尝试使用 df.Col1.str.strip().str.rsplit(...)。不错! - cs95

1
你可以使用rsplit函数。它会从字符串的右侧开始分割。
pd.DataFrame(df.Col1.str.rsplit(' ',1).tolist(), columns = ['Name','Area'])

Result:
    Name                Area
0   APPLEGATE WINERY    455.292049
1   AMAND FARM          849.827192
2   COBB FARM ST       1039.49357
3   DIRIGIA            2048.947284

0
尝试这个正则表达式:
df.Col1.str.extract('(.*\S)\s+([\d\.]+)')

输出:

                  0            1
0  APPLEGATE WINERY   455.292049
1        AMAND FARM   849.827192
2      COBB FARM ST   1039.49357
3           DIRIGIA  2048.947284

1
意识到了并已经修正。 - Quang Hoang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接