pandas - 在字符串列上合并不起作用(bug?)

use*_*984 16 python mysql merge pandas

我正在尝试在两个数据帧之间进行简单的合并.它们来自两个不同的SQL表,其中连接键是字符串:

>>> df1.col1.dtype
dtype('O')
>>> df2.col2.dtype
dtype('O')
Run Code Online (Sandbox Code Playgroud)

我尝试使用以下方法合并它们:

>>> merge_res = pd.merge(df1, df2, left_on='col1', right_on='col2')
Run Code Online (Sandbox Code Playgroud)

内部联接的结果为空,这首先提示我交集中可能没有任何条目:

>>> merge_res.shape
(0, 19)
Run Code Online (Sandbox Code Playgroud)

但是当我尝试匹配单个元素时,我发现这真的很奇怪.

# Pick random element in second dataframe
>>> df2.iloc[5,:].col2
'95498208100000'

# Manually look for it in the first dataframe
>>> df1[df1.col1 == '95498208100000']
0 rows × 19 columns
# Empty, which makes sense given the above merge result

# Now look for the same value as an integer
>>> df1[df1.col1 == 95498208100000]
1 rows × 19 columns
# FINDS THE ELEMENT!?!
Run Code Online (Sandbox Code Playgroud)

因此,列使用'object'dtype定义.将它们作为字符串搜索不会产生任何结果.将它们作为整数搜索会返回结果,我认为这就是为什么合并不起作用的原因..

有什么想法发生了什么?

它几乎就像Pandas转换df1.col1为整数只是因为它可以,即使它应该在匹配时被视为字符串.

(我尝试使用示例数据框复制这个,但是对于小例子,我没有看到这种行为.关于如何找到更具描述性的示例的任何建议也将受到赞赏.)

use*_*984 24

问题是objectdtype具有误导性.我认为这意味着所有项目都是字符串.但显然,在阅读文件时,pandas会将一些元素转换为int,并将剩余部分保留为字符串.

解决方案是确保每个字段都是一个字符串:

>>> df1.col1 = df1.col1.astype(str)
>>> df2.col2 = df2.col2.astype(str)
Run Code Online (Sandbox Code Playgroud)

然后合并按预期工作.

(我希望能有指定的方式dtypestr...)

  • 奇怪的。您的解决方案有效。但是无论是之前还是之后,所讨论的变量的 dtype 都是“O”。我想,就像你提到的,这些对象类型背后还有更多的东西。希望它更透明。 (4认同)
  • 上帝保佑你这个好人!你帮我节省了好几个小时的时间! (2认同)

see*_*spi 10

我遇到了df.col = df.col.astype(str)解决方案无效的案例.原来问题在于编码.

我的原始数据如下所示:

In [72]: df1['col1'][:3]
Out[73]: 
             col1
0  dustin pedroia
1  kevin youkilis
2     david ortiz

In [72]: df2['col2'][:3]
Out[73]: 
             col2
0  dustin pedroia
1  kevin youkilis
2     david ortiz
Run Code Online (Sandbox Code Playgroud)

使用.astype(str)合并后仍然没有工作,所以我执行了以下操作:

df1.col1 = df1.col1.str.encode('utf-8')
df2.col2 = df2.col2.str.encode('utf-8')
Run Code Online (Sandbox Code Playgroud)

并找到了差异:

In [95]: df1
Out[95]: 
                       col1
0  b'dustin\xc2\xa0pedroia'
1  b'kevin\xc2\xa0youkilis'
2     b'david\xc2\xa0ortiz'

In [95]: df2
Out[95]: 
                col2
0  b'dustin pedroia'
1  b'kevin youkilis'
2     b'david ortiz'
Run Code Online (Sandbox Code Playgroud)

在这一点上,我所要做的就是df1.col1 = df1.col1.str.replace('\xa0',' ')在解码的df1.col1变量上运行(即在运行之前.str.encode('utf-8'))并且合并完美.

注意:无论我更换什么,我总是习惯.str.encode('utf-8')检查它是否有效.

另外

使用正则表达式和Spyder IDE中的变量资源管理器为Anaconda我发现了以下区别.

import re
#places the raw string into a list
df1.col1 = df1.col1.apply(lambda x: re.findall(x, x))  
df2.col2 = df2.col2.apply(lambda x: re.findall(x, x))
Run Code Online (Sandbox Code Playgroud)

我的df1数据变成了这个(从Spyder复制并粘贴):

['dustin\xa0pedroia']
['kevin\xa0youkilis']
['david\xa0ortiz']
Run Code Online (Sandbox Code Playgroud)

这只是一个略有不同的解决方案.我不知道在什么情况下第一个例子不起作用,第二个例子但是我想提供两个以防万一有人遇到它:)


Fer*_*ras 10

谢谢,@seeiespi ..str.encode('utf-8') 帮助我弄清楚我的字符串需要被剥离,如下所示

20                 b'Belize '   ...     0,612
21                  b'Benin '   ...     0,546
Run Code Online (Sandbox Code Playgroud)

解决方案是使用条带

df1.col1 = df1.col1.str.strip()
df1.col1 = df1.col1.str.strip()
Run Code Online (Sandbox Code Playgroud)