【问题标题】:Python Pandas: Compare values of two dataframes with different columns names by ID or rowPython Pandas:按 ID 或行比较具有不同列名的两个数据框的值
【发布时间】:2017-03-29 08:12:20
【问题描述】:

我有两个来自不同来源的数据框(我们将它们命名为 M 和 K)。它们有不同的列名,两个数据框中唯一相同的一列是 ID 列 (M[id] == K[id])。

两个数据帧中的行数相等;许多列是不同的。

目标是创建一个矩阵,该矩阵将有多少列具有相同 ID(或行)的相同值。矩阵 (MK) 的大小为 M.columns X K.columns。每个单元格存储 M.column 和 K.column 对的匹配值的计数。单元格中的最大数量是 M 或 K 的行数,因为它们是相同的。应忽略缺失值 (NaN)。

用数字说话 =)

data_M = {'id': ['id1', 'id2', 'id3', 'id4', 'id5', 'id6'],
        'm1': ['a', 'b', 'c', 'd', 'e', 2],
        'm2': [1, 2, 3, 4, np.nan, 1],
        'm3': ['aa','b','cc','d','ff', 3],
        'm4': [4, 6, 3, 4, np.nan, 2],
        'm5': ['b', 6, 'a', 4, np.nan, 1],
        }
data_K = {'id': ['id1', 'id2', 'id3', 'id4', 'id5', 'id6'],
        'k1': ['z', 'bb', 'c', 'd', 'e', 4],
        'k2': [1, 2, 32, 5, np.nan, 1],
        'k3': ['aa','b','cc','d','ff', 1],
        'k4': [4, 2, 2, 4, np.nan, 4],
        'k5': [4, 1, 'as', 4, np.nan, 2],
        'k6': ['aa', 1, 'a', 3, np.nan, 2],
        }
M = pd.DataFrame(data_M, columns = ['id','m1','m2','m3','m4','m5']) 
K = pd.DataFrame(data_K, columns = ['id','k1','k2','k3','k4', 'k5','k6'])

M 和 K 输出

M
Out[2]: 
    id m1   m2  m3   m4   m5
0  id1  a  1.0  aa  4.0    b
1  id2  b  2.0   b  6.0    6
2  id3  c  3.0  cc  3.0    a
3  id4  d  4.0   d  4.0    4
4  id5  e  NaN  ff  NaN  NaN
5  id6  2  1.0   3  2.0    1

K
Out[3]: 
    id  k1    k2  k3   k4   k5   k6
0  id1   z   1.0  aa  4.0    4   aa
1  id2  bb   2.0   b  2.0    1    1
2  id3   c  32.0  cc  2.0   as    a
3  id4   d   5.0   d  4.0    4    3
4  id5   e   NaN  ff  NaN  NaN  NaN
5  id6   4   1.0   1  4.0    2    2

在第一次比较 id=='id1' 后,MK 矩阵应如下所示:

    id  m1  m2  m3  m4  m5
id  1   0   0   0   0   0
k1  0   0   0   0   0   0
k2  0   0   1   0   0   0
k3  0   0   0   1   0   0
k4  0   0   0   0   1   0
k5  0   0   0   0   1   0
k6  0   0   0   1   0   0

第二个(id=='id2')应该是下一个:

    id  m1  m2  m3  m4  m5
id  2   0   0   0   0   0
k1  0   0   0   0   0   0
k2  0   0   2   0   0   0
k3  0   0   0   2   0   0
k4  0   0   1   0   1   0
k5  0   0   0   0   1   0
k6  0   0   0   1   0   0

最后,每个单元格将转换为匹配值的百分比。

最后一个。 从理论上讲,每个 ID 可能不止一行。但是,对于当前的问题,情况并非如此。不过如果你有灵感,欢迎你解决'一般情况'^_^

非常感谢。

【问题讨论】:

    标签: python pandas numpy dataframe


    【解决方案1】:

    使用numpy广播和pd.Panel的方法

    m = M.values[:, 1:]
    k = K.values[:, 1:]
    
    p = pd.Panel(
        (m[:, None] == k[:, :, None]).astype(np.uint8),
        M.id.values, K.columns[1:], M.columns[1:])
    

    然后访问每个id

    p['id1']
    
        m1  m2  m3  m4  m5
    k1   0   0   0   0   0
    k2   0   1   0   0   0
    k3   0   0   1   0   0
    k4   0   0   0   1   0
    k5   0   0   0   1   0
    k6   0   0   1   0   0
    

    或者使用pandasgroupby

    df = M.set_index('id').join(K.set_index('id'))
    
    def row_comp(r):
        m = r.filter(like='m')
        k = r.filter(like='k')
        return pd.DataFrame(
            (m.values == k.values.T).astype(np.uint8),
            k.columns, m.columns
        )
    
    
    df.groupby(level=0).apply(row_comp)
    
            m1  m2  m3  m4  m5
    id                        
    id1 k1   0   0   0   0   0
        k2   0   1   0   0   0
        k3   0   0   1   0   0
        k4   0   0   0   1   0
        k5   0   0   0   1   0
        k6   0   0   1   0   0
    id2 k1   0   0   0   0   0
        k2   0   1   0   0   0
        k3   1   0   1   0   0
        k4   0   1   0   0   0
        k5   0   0   0   0   0
        k6   0   0   0   0   0
    id3 k1   1   0   0   0   0
        k2   0   0   0   0   0
        k3   0   0   1   0   0
        k4   0   0   0   0   0
        k5   0   0   0   0   0
        k6   0   0   0   0   1
    id4 k1   1   0   1   0   0
        k2   0   0   0   0   0
        k3   1   0   1   0   0
        k4   0   1   0   1   1
        k5   0   1   0   1   1
        k6   0   0   0   0   0
    id5 k1   1   0   0   0   0
        k2   0   0   0   0   0
        k3   0   0   1   0   0
        k4   0   0   0   0   0
        k5   0   0   0   0   1
        k6   0   0   0   0   1
    id6 k1   0   0   0   0   0
        k2   0   1   0   0   1
        k3   0   1   0   0   1
        k4   0   0   0   0   0
        k5   1   0   0   1   0
        k6   1   0   0   1   0
    

    【讨论】:

    • 非常聪明的解决方案!
    • @piRSquared 游戏结束
    • @Boud 我不确定那是什么意思……但我还是喜欢。然后我的铃声在我脑海里轻轻响起……塞尔达主题曲
    猜你喜欢
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 2021-05-09
    相关资源
    最近更新 更多