pandas - 合并字符串列不起作用(错误?)

Posted

技术标签:

【中文标题】pandas - 合并字符串列不起作用(错误?)【英文标题】:pandas - Merging on string columns not working (bug?) 【发布时间】:2017-01-27 17:20:26 【问题描述】:

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

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

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

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

inner join的结果是空的,首先提示我交集可能没有任何条目:

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

因此,列是使用“对象”dtype 定义的。将它们作为字符串搜索不会产生任何结果。将它们作为整数搜索确实会返回结果,我认为这就是合并在上面不起作用的原因..

有什么想法吗?

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

(我尝试使用示例数据框复制此内容,但对于小示例,我没有看到这种行为。任何关于如何找到更具描述性示例的建议也将不胜感激。)

【问题讨论】:

看起来你的列中混合了 dtypes,我建议首先尝试将所有值强制为数字所以df1['col1'] = df1['col1'].astype(int) 这可能会失败,这意味着你有一些 str 值不能表示为 int,所以接下来尝试df1['col1'] = pd.to_numeric(df1['col1'], errors='coerce'),它将强制将 duff 值设置为NaN,它可以 啊,谢谢@EdChum!一些值可以转换为int,但其他值不能。因此,该列的正确 dtype 应该是 str,但由于这不是正确的 dtype,我认为 object 会起作用。但是当我手动将所有内容转换为str 时,合并确实有效。谢谢! 你能否发布一个答案,然后在几天后接受你自己的答案,这样这个问题就不会没有答案了,谢谢 【参考方案1】:

这个答案为我解决了:

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

来自Pandas merge issue on key of object type containing number and string values

【讨论】:

【参考方案2】:

您的列可能存在一些差异或导致此错误的空格。

首先检查您的列类型以及项目之间是否有任何不同

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.

【讨论】:

【参考方案3】:

上述解决方案都不适合我,因为合并实际上已正确完成,但索引却搞砸了。删除索引为我解决了它:

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

【讨论】:

哇,这出乎意料。谢谢,这个答案对我帮助很大;合并两个字符串列,其中一个是唯一的。 pd.merge 有它的怪癖。【参考方案4】:

谢谢,@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()

【讨论】:

【参考方案5】:

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

此时我所要做的就是在解码后的 df1.col1 变量上运行 df1.col1 = df1.col1.str.replace('\xa0',' ')(即在运行 .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 复制和粘贴):

['dustin\xa0pedroia']
['kevin\xa0youkilis']
['david\xa0ortiz']

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

【讨论】:

非常有帮助!有同样的问题,结果是编码,我没想到!谢谢! 谢谢,这是 \xa0 问题,因为我的案例使用 beautifulsoup 进行网络抓取。更换它解决了问题【参考方案6】:

问题在于 object dtype 具有误导性。我认为这意味着所有项目都是字符串。但显然,在读取文件时,pandas 正在将一些元素转换为整数,并将其余元素保留为字符串。

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

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

然后合并按预期工作。

(我希望有一种方法可以指定 dtypestr...)

【讨论】:

很奇怪。你的解决方案奏效了。但是在之前和之后,有问题的变量的 dtype 都是“O”。我想,就像你提到的那样,这些对象类型还有更多内容。希望它更透明。 上帝保佑你这个好人!你节省了我抓头的时间! 当您在 excel 中为此类列应用 vlookup 时,也会发生同样的情况。我在快速查找时得到了错误的结果,所以求助于 pandas 但在那里得到了相同的输出(nan)。

以上是关于pandas - 合并字符串列不起作用(错误?)的主要内容,如果未能解决你的问题,请参考以下文章

Python Pandas 合并不起作用

从 pandas DataFrame 中的多个字符串列中删除子字符串

pandas - 合并日期列不起作用

大 TSV 文件中主要为整数的字符串列的不一致 pandas read_csv dtype 推断

字符串连接在猪中不起作用

从 Pandas DF 的字符串列中提取数字