使用Python对一列中的多个值进行复杂的提取和转换



我如何获得"df"数据帧的背景:

这些数据被从SQL Server提取到Python中,然后使用Pandas:转换为数据帧

Backup = pyodbc.connect(
'Driver={SQL Server};'
'Server=testSQLEXPRESS;'
'Database=Backup;'
'Trusted_Connection=yes;'
)
crsr = Backup.cursor()
for table_name in crsr.tables(tableType='TABLE'):
print(table_name)
cursor = Backup.cursor()
sql = "select TOP 20* from dbo.table$"
cursor.execute(sql)
for data in cursor.fetchall():
print (data)

df = pandas.read_sql(sql,Backup)
df

我的df数据帧中有一列,它由如下值组成:

Location
AM  -  Equi A2 Amsterdam
AM  -  Equi A2 Amsterdam
AM  -  Equi A2 Amsterdam
GRU  - log Equ SP São Paulo
GRU  - log Equ SP São Paulo
GRU  - log Equ SP São Paulo
SJC1 - DR Santa Clara
IAD - Terremark NAV Culpepper
HKG1 - Equin HK Hong Kong

困境:

如何仅提取实际的地点,如:圣保罗、阿姆斯特丹、卡尔佩珀、香港等?

期望输出:

Amsterdam
Amsterdam
Amsterdam
São Paulo
São Paulo
São Paulo
Santa Clara
Culpepper
Hong Kong

问题是,我不能只在最后一个空格上分开,因为国家有两个词,被一个空格分开。(香港,圣保罗(

我一直在做的事情:

df["New_Column"]= df["Location"].str.split(" ", n = 1, expand = True) 

我也在使用str函数(来自stackoverflow成员的建议(

df.str.extract() 

我有了这个正则表达式,它有点复杂,所以我会为您分解它。

创建数据:

data = """
AM  -  Equi A2 Amsterdam
AM  -  Equi A2 Amsterdam
AM  -  Equi A2 Amsterdam
GRU  - log Equ SP São Paulo
GRU  - log Equ SP São Paulo
GRU  - log Equ SP São Paulo
SJC1 - DR Santa Clara
IAD - Terremark NAV Culpepper
HKG1 - Equin HK Hong Kong
""".strip().split("n")
df = pd.DataFrame(data, columns=["location"])
df["location"] = df["location"].str.strip()
print(df)
location
0       AM  -  Equi A2 Amsterdam
1       AM  -  Equi A2 Amsterdam
2       AM  -  Equi A2 Amsterdam
3    GRU  - log Equ SP São Paulo
4    GRU  - log Equ SP São Paulo
5    GRU  - log Equ SP São Paulo
6          SJC1 - DR Santa Clara
7  IAD - Terremark NAV Culpepper
8      HKG1 - Equin HK Hong Kong

通过Series.str.extract应用我们的正则表达式

df["city"] = df["location"].str.extract(r"-.*s+[A-Z0-9]+s+(?P<city>.*)")
print(df)
location         city
0       AM  -  Equi A2 Amsterdam    Amsterdam
1       AM  -  Equi A2 Amsterdam    Amsterdam
2       AM  -  Equi A2 Amsterdam    Amsterdam
3    GRU  - log Equ SP São Paulo    São Paulo
4    GRU  - log Equ SP São Paulo    São Paulo
5    GRU  - log Equ SP São Paulo    São Paulo
6          SJC1 - DR Santa Clara  Santa Clara
7  IAD - Terremark NAV Culpepper    Culpepper
8      HKG1 - Equin HK Hong Kong    Hong Kong

正则表达式解释r"-.*s+[A-Z0-9]+s+(?P<city>.*)$":

  • -找到了hypen。我们可以忽略连字符之前的所有内容
  • s+[A-Z0-9]s+找到连字符后,找到一个只包含大写字母和/或数字的子字符串,此外,该子字符串必须被1个或多个空格包围
  • (?P<city>.*)$找到上一步后,将字符串的其余部分用作城市名称,并将其存储在捕获组中

虽然正则表达式是非常有用的工具,但它们确实会留下相当多的边缘情况。我这里的表达式适用于您的数据,但请确保对整个数据集进行一些测试和调整,因为在某些情况下,如果您的字符串与此处确定的模式不匹配,它仍然可能返回NaN。

更新:用户已声明数据来自SQL Server。因此,示例代码已经更新,以显示从SQL中提取数据和随后提取城市的示例。(以前,位置数据是从list合成的。(

原始评论:
正如我的评论中所建议的,这里有一个如何使用regex从位置字符串解析城市的示例。

此外,此示例(可选(使用了unidecode库,该库将非ASCII(扩展unicode(字符转换为ASCII,因为它们可能会引起regex。在文本处理过程中,将非ASCII字符转换为ASCII是一种常见的做法。

正则表达式模式——尽管它看起来很像官样文章,但它可以执行以下操作:

  • 开始是字符串的开始,用于隔离"XX-"模式
  • 隔离以下"xxx"字符
  • 隔离"XXN"以确定从何处开始命名捕获
  • 命名捕获(由?P<city>[ws]+模式指示(用于将城市名称提取到city列中

注意在字符串的开头和结尾使用^$。它们告诉模式从字符串的开头(^(开始,并一直匹配到末尾($(。通常,显式匹配整个字符串非常有用。否则,如果只匹配部分字符串,则可能会得到意外结果。

这里有一个指向regex构建/测试站点的链接,我觉得在编写新模式时非常有用。

示例代码:

import pandas as pd
import re
from unidecode import unidecode  # optional
# Database connection code ...
# ...
# ...
# Query data from SQL into a DataFrame.
# We use MySQL, so this line will be different for you;
# use your existing code here.
df = pd.read_sql(sql="select * from locations", con=engine)
# Define regex pattern.
exp = re.compile(r'^[A-Z0-9s-]+[ws]+[A-Z0-9]+s(?P<city>[ws]+)$')
# Convert non-ASCII characters to ASCII. (optional)
# df['locations'] = df['locations'].apply(unidecode)    # Extract the city name.
df['cities'] = df['locations'].str.extract(exp, expand=True)

来自SQL的原始数据:

locations
0       AM  -  Equi A2 Amsterdam
1       AM  -  Equi A2 Amsterdam
2       AM  -  Equi A2 Amsterdam
3    GRU  - log Equ SP São Paulo
4    GRU  - log Equ SP São Paulo
5    GRU  - log Equ SP São Paulo
6          SJC1 - DR Santa Clara
7  IAD - Terremark NAV Culpepper
8      HKG1 - Equin HK Hong Kong

分析的输出:

locations       cities
0       AM  -  Equi A2 Amsterdam    Amsterdam
1       AM  -  Equi A2 Amsterdam    Amsterdam
2       AM  -  Equi A2 Amsterdam    Amsterdam
3    GRU  - log Equ SP São Paulo    São Paulo
4    GRU  - log Equ SP São Paulo    São Paulo
5    GRU  - log Equ SP São Paulo    São Paulo
6          SJC1 - DR Santa Clara  Santa Clara
7  IAD - Terremark NAV Culpepper    Culpepper
8      HKG1 - Equin HK Hong Kong    Hong Kong

最新更新