我试图在两个数据帧之间做一个简单的合并。它们来自两个不同的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)
则合并按预期工作。
(我希望有一种方法来指定str
的dtype
…)
我遇到了一个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')
对我有用。我是说两个在一起