【问题标题】:pandas - Merging on string columns not working (bug?)pandas - 合并字符串列不起作用(错误?)
【发布时间】: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 时,合并确实有效。谢谢!
  • 你能否发布一个答案,然后在几天后接受你自己的答案,这样这个问题就不会没有答案了,谢谢

标签: python mysql pandas merge


【解决方案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)。
        猜你喜欢
        • 2020-08-18
        • 1970-01-01
        • 2022-01-19
        • 1970-01-01
        • 1970-01-01
        • 2016-02-01
        • 2017-10-08
        • 2013-04-13
        相关资源
        最近更新 更多