根据条件熊猫数据框拆分列数据

时间:2020-03-27 07:04:03

标签: python-3.x pandas dataframe

我有一个庞大的数据集,正在寻找可以将我的街道地址分为两列Street NumberStreet Name的内容。

由于我首先需要处理街道地址,然后检查拆分的第一个索引是否有数字,因此我试图找出如何有效地做到这一点。

到目前为止,我的工作代码如下所示。我创建了两个函数,一个用于从街道地址中提取街道编号数据,而另一个函数则是从街道地址中替换该街道编号的第一个匹配项。

def extract_street_number(row):
      if any(map(str.isdigit, row.split(" ")[0])):
        return row.split(" ")[0]


def extract_street_name(address, streetnumber):
    if streetnumber:
        return address.replace(streetnumber, "", 1)
    else:
        return address

然后使用apply函数具有两列。

df[street_number] = df.apply(lambda row: extract_street_number(row[address_col]), axis=1)
df[street_name] = df.apply(lambda row: extract_street_name(row[address_col], row[street_number]), axis=1)

我想知道是否有更有效的方法来做到这一点?基于此当前例程,在处理街道名称列之前,我需要先构建“街道编号列”。

我正在考虑在地址列的第一次迭代中构建两个系列。伪代码就是这样,我无法弄清楚如何用python进行编码。

伪代码:

  1. 根据遇到非数字字符的第一个空格将地址分为两列: street_data = address.split(" ", maxsplit=1)

  2. 如果street_data [0]有数字,则以这种方式返回列:

      df[street_number] = street_data[0]
      df[street_name] = street_data[1]
  1. 否则,如果street_data [0]不是数字,则以这种方式返回列:
      df[street_number] = ""
      df[street_name] = street_data[0] + " " + street_data[1]
      # or just simply the address
      df[street_name] = address

顺便说一下,这是数据的工作样本:

# In
df = pd.DataFrame({'Address':['111 Rubin Center', 'Monroe St', '513 Banks St', '5600 77 Center Dr', '1013 1/2 E Main St', '1234C Main St', '37-01 Fair Lawn Ave']})

# Out
   Street_Number    Street_Name
0           111     Rubin Center
1                   Monroe St
2           513     Banks St
3        560 77     Center Dr
4      1013 1/2     E Main St
5         1234C     Main St
6         37-01     Fair Lawn Ave

3 个答案:

答案 0 :(得分:1)

TL;DR: 这可以通过三个步骤来实现-

步骤 1-

df['Street Number'] = [street_num[0] if any(i.isdigit() for i in street_num[0]) else 'N/A' for street_num in df.Address.apply(lambda s: s.split(" ",1))]

步骤 2-

df['Street Address'] = [street_num[1] if any(i.isdigit() for i in street_num[0]) else 'N/A' for street_num in df.Address.apply(lambda s: s.split(" ",1))]

步骤 3-

df['Street Address'].loc[df['Street Address'].str.contains("N/A") == True] = df1['Address'].loc[df1['Street Address'].str.contains("N/A") == True]

说明-

在数据框中添加了另外两个测试用例以提高代码灵活性(第 7,8 行)- Initial Dataframe

第 1 步 - 我们将这里的街道号码与地址分开。这是通过在拆分地址字符串并初始化为 Street Number 列之后从列表中切分第一个元素来完成的。 如果第一个元素不包含数字,则将 N/A 附加到 Street Number 列中。

Step 1

第 2 步 - 由于切片字符串中的第一个元素包含 Street Number,因此第二个元素必须是 Street Address,因此附加到 {{1} } 列。

Step 2

第 3 步 - 由于第 2 步,不包含数字且由此解析的“地址”的 Street Address 变为“N/A” -

Step 3

因此,经过几个小时的努力,我们可以分三步解决这个问题。

答案 1 :(得分:0)

反映您的伪代码的

解决方案如下。 首先让我们划分“地址”并存储在某个地方

new = df["Address"].str.split(" ", n = 1, expand = True)
df["First Part"]= new[0]
df["Last Part"]= new[1] 

接下来让我们写下条件

cond1 = df['First Part'].apply(str.isdigit)
cond2 = df['Last Part'].apply(str.isdigit)

现在检查满足给定条件的条件

df.loc[cond1 & ~cond2, "Street"] = df.loc[cond1 & ~cond2, "Last Part"]
df.loc[cond1 & ~cond2, "Number"] = df.loc[cond1 & ~cond2, "First Part"]
df.loc[~cond1 & ~cond2, "Street"] = df.loc[~cond1 & ~cond2, ['First Part', 'Last Part']].apply(lambda x: x[0] + ' ' + x[1], axis = 1)

最后,让我们清理那些辅助列

df.drop(["First Part", "Last Part"], axis = 1, inplace=True)
df

   Address            Street         Number
0  111 Rubin Center   Rubin Center   111
1  Monroe St          Monroe St      NaN
2  513 Banks St       Banks St       513

答案 2 :(得分:0)

#mock test
df = pd.DataFrame({'Address':['111 Rubin Center', 'Monroe St',
                              '513 Banks St', 'Banks 513 St',
                              'Rub Cent 111']})

除非我缺少任何东西,否则一些正则表达式应该可以解决您的请求:

#gets number only if it starts the line
df['Street_Number'] = df.Address.str.extract(r'(^\d+)')
#splits only if number is at the start of the line
df['Street_Name'] = df.Address.str.split('^\d+').str[-1]


  Address           street_number   street_name
0   111 Rubin Center    111         Rubin Center
1   Monroe St           NaN         Monroe St
2   513 Banks St        513         Banks St
3   Banks 513 St        NaN         Banks 513 St
4   Rub Cent 111        NaN         Rub Cent 111

让我知道这在哪里下跌

相关问题