Pandas:如何合并key1上的2个数据帧。结构端部(键2)

2024-06-01 01:46:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我想找到在key1上合并2个数据帧的最佳方法。结构端部(关键2),例子有时比文字更好:

 i want to merge df1 and df2  on product.str.endswith(color)

 df1:
    index product
    1     a208-BLACK 
    2     a2008-WHITE
    3     x307-PEARL-WHITE
    4     aa-b307-WHITE

 df2:
    index color       code
    1     BLACK       X1001
    2     WHITE       X7005
    3     PEARL-WHITE X7055

获得:

^{pr2}$

有什么想法吗?在


Tags: 数据方法indexproduct结构例子关键color
3条回答

您可以使用vectorized string method^{},以及regex模式r'-([A-Z-]+)$'来查找颜色。在

df1['color'] = df1['product'].str.findall(r'-([A-Z-]+)$').str[0]

然后pd.merge(df1, df2)将在公共列上合并,在本例中是color列:

^{pr2}$

例如

import io
import pandas as pd

df1 = '''\
index product
1     a208-BLACK 
2     a2008-WHITE
3     x307-PEARL-WHITE
4     aa-b307-WHITE'''
df1 = pd.read_table(io.BytesIO(df1), sep='\s+', index_col=0)

df2 = '''\
index color       code
1     BLACK       X1001
2     WHITE       X7005
3     PEARL-WHITE X7055'''
df2 = pd.read_table(io.BytesIO(df2), sep='\s+', index_col=0)
df1['color'] = df1['product'].str.extract(r'-([A-Z-]+)$')
print(pd.merge(df1, df2))

收益率

            product        color   code
0        a208-BLACK        BLACK  X1001
1       a2008-WHITE        WHITE  X7005
2     aa-b307-WHITE        WHITE  X7005
3  x307-PEARL-WHITE  PEARL-WHITE  X7055

regex模式r'-([A-Z-]+)$'表示

-              # match a literal hyphen
(              # followed by a group 
 [A-Z-]+       # of 1-or-more capital letters or hyphens
)              # end of group 
$              # followed by end of line

一些简洁的解决方案:

import pandas as pd

df1['color'] = df1['product'].apply(lambda x: re.sub('^[^ALPHA:]*-(.*)', '\\1', x))

pd.merge(df1, df2, on='color')

#            product        color   code
#0        a208-BLACK        BLACK  X1001
#1       a2008-WHITE        WHITE  X7005
#2  x307-PEARL-WHITE  PEARL-WHITE  X7055
#3     aa-b307-WHITE        WHITE  X7005

我不是正则表达式专家,最后一个是最难处理的,但以下工作:

In [402]:

df['code'] = df['product'].str.split('-').str[1:].str.join('-').str.findall(r'[A-Z]+').str.join('-').map(df1.set_index('color')['code'])
df
Out[402]:
                product   code
index                         
1            a208-BLACK  X1001
2           a2008-WHITE  X7005
3      x307-PEARL-WHITE  X7055
4         aa-b307-WHITE  X7005

基本上,我将产品代码分割在-上,并将所有元素放在第一个破折号的右侧。在

剩下的是:

^{pr2}$

然后我把破折号放回去,用正则表达式只查找大写字母字符,这处理最后一个,重新连接。在

最后一位是在对color列设置索引后,在另一个df上调用map,这将对df中的颜色值执行查找并返回相应的代码。在

regex不是万无一失的,但它适用于您的数据集。在

编辑

我现在意识到我们不需要那么多人加入:

In [409]:

df['code'] = df['product'].str.findall(r'[A-Z]+').str.join('-').map(df1.set_index('color')['code'])
df
Out[409]:
                product   code
index                         
1            a208-BLACK  X1001
2           a2008-WHITE  X7005
3      x307-PEARL-WHITE  X7055
4         aa-b307-WHITE  X7005

计时

In [414]:


%%timeit 
import re
df['color'] = df['product'].apply(lambda x: re.sub('^[^ALPHA:]*-(.*)', '\\1', x))

pd.merge(df, df1, on='color')
1 loops, best of 3: 4.09 ms per loop
In [416]:

%%timeit
df['code'] = df['product'].str.findall(r'[A-Z]+').str.join('-').map(df1.set_index('color')['code'])

100 loops, best of 3: 1.63 ms per loop

str方法比使用lambda快2倍以上,这可能并不奇怪,因为str方法是向量化的,就像调用map。在

更新时间

In [7]:

%%timeit
df1['color'] = df1['product'].str.extract(r'-([A-Z-]+)$')
pd.merge(df1, df2)
100 loops, best of 3: 4.51 ms per loop
In [9]:

%%timeit
df1['code'] = df1['product'].str.findall(r'[A-Z]+').str.join('-').map(df2.set_index('color')['code'])
100 loops, best of 3: 3.87 ms per loop
In [10]:

%%timeit 
import re
df1['color'] = df1['product'].apply(lambda x: re.sub('^[^ALPHA:]*-(.*)', '\\1', x))

pd.merge(df1, df2, on='color')
100 loops, best of 3: 4.79 ms per loop

所以@unutbu的答案比beaveau上校的答案稍快一些,但在这里使用地图仍然更快。在

事实上,如果我们将@unutbu的regexstr方法与map结合起来,我们会比我原来的方法更快:

In [12]:

%%timeit
df1['product'].str.extract(r'-([A-Z-]+)$').map(df2.set_index('color')['code'])
100 loops, best of 3: 2.17 ms per loop

所以在这里使用map比合并快2倍

相关问题 更多 >