pandas -合并字符串列不工作(bug?)



我试图在两个数据帧之间做一个简单的合并。它们来自两个不同的SQL表,其中连接键是字符串:

>>> df1.col1.dtype
dtype('O')
>>> df2.col2.dtype
dtype('O')

我试着用这个来合并它们:

>>> merge_res = pd.merge(df1, df2, left_on='col1', right_on='col2')

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

>>> merge_res.shape
(0, 19)

但是当我尝试匹配单个元素时,我看到了这个非常奇怪的行为。

# 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!?!

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

知道是怎么回事吗?

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

(我尝试使用示例数据框架来复制此操作,但对于小示例,我没有看到此行为。如果我能找到一个更具描述性的例子,我将不胜感激)

问题是object dtype具有误导性。我以为它的意思是所有项都是字符串。但显然,在读取文件时,pandas将一些元素转换为整型,并将其余元素保留为字符串。

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

>>> df1.col1 = df1.col1.astype(str)
>>> df2.col2 = df2.col2.astype(str)

则合并按预期工作。

(我希望有一种方法来指定strdtype…)

我遇到了一个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

和使用.astype(str)合并后仍然不工作,所以我执行以下命令:

df1.col1 = df1.col1.str.encode('utf-8')
df2.col2 = df2.col2.str.encode('utf-8')

,并能找到差异:

In [95]: df1
Out[95]: 
                       col1
0  b'dustinxc2xa0pedroia'
1  b'kevinxc2xa0youkilis'
2     b'davidxc2xa0ortiz'
In [95]: df2
Out[95]: 
                col2
0  b'dustin pedroia'
1  b'kevin youkilis'
2     b'david ortiz'

此时,我所要做的就是在解码后的df1上运行df1.col1 = df1.col1.str.replace('xa0',' ')。col1变量(即在运行.str.encode('utf-8')之前)和合并工作完美。

注意:不管我要替换什么,我总是使用.str.encode('utf-8')来检查它是否工作。

或者

使用正则表达式和变量资源管理器在Spyder IDE for 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))

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

['dustinxa0pedroia']
['kevinxa0youkilis']
['davidxa0ortiz']

有一个稍微不同的解决方案。我不知道在什么情况下第一个例子不会工作,第二个会,但我想提供这两个以防有人碰到它:)

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

20                 b'Belize '   ...     0,612
21                  b'Benin '   ...     0,546

解决方案是使用条带

df1.col1 = df1.col1.str.strip()
df1.col1 = df1.col1.str.strip()

以上解决方案都不适合我,因为合并实际上是正确完成的,但索引弄乱了。删除索引为我解决了这个问题:

df['sth'] = df.merge(df2, how='left', on=['x', 'y'])['sth'].values

这个答案为我解决了这个问题:

pd.merge(df1.assign(x=df1.x.astype(str)), 
         df2.assign(x=df2.x.astype(str)), 
         how='left', on='x')

可能您的列有一些差异或空白导致此错误。

首先检查你的列类型,如果条目之间有任何不同

df1.col1 = df1.col1.str.encode('utf-8')
df2.col2 = df2.col2.str.encode('utf-8')

如果两者有差异,可以使用

df1.col1 = df1.col1.str.replace("this", "for that")

或者如果有空格

df1.col1 = df1.col1.apply(str).str.strip()
# This apply(str) is being used because without it, the program returns an error related to being enable to convert from byte.

此步骤:

df1.col1 = df1.col1.str.strip()
df1.col1 = df1.col1.str.strip()

,然后执行以下步骤:

pd.merge(df1.assign(x=df1.x.astype(str)), 
         df2.assign(x=df2.x.astype(str)), 
         how='left', on='x')

对我有用。我是说两个在一起

最新更新