繁体   English   中英

比较两个数据框列

[英]Comparing two dataframes columns

我有两个结构相同的数据框。

两者都必须采用以下格式:

file_name | country_name | country_code | .....

我想比较两者,并获得每列的相等百分比。

第二个数据框是测试 dataframe,它包含真实值。 一些值是 NaN,应该被忽略。 到目前为止,我已经成功地比较了两者,并得到了每列相等样本的总数,我的问题是将它们中的每一个除以相关样本的总数(第二个数据帧中没有 NaN),以一种“好的方式”。

例如:

df1

file_name | country_name 
    1            a
    2            b
    3            d
    4            c

df2

file_name | country_name 
    1            a
    2            b
    3            nan
    4            d

我预计此列的 output 为 66%,因为 3 个相关样本中有 2 个具有相同的值,而第 4 个是 nan,因此在计算中被忽略。

到目前为止我做了什么:

test_set = pd.read_excel(file_path)
test_set = test_set.astype(str)
a_set = pd.read_excel(file2_path)
a_set = a_set.astype(str)
merged_df = a_set.merge(test_set, on='file_name')
for field in fields:
    if field == 'file_name':
        continue
    merged_df[field] = merged_df.apply(lambda x: 0 if x[field + '_y'] == 'nan' else 1 if x[field + '_x'].lower() == x[field + '_y'].lower() else 0, axis=1)

scores = merged_df.drop('file_name', axis=1).sum(axis=0)

这给了我这些(正确的)结果:

country_name      14
country_code       0
state_name         4
state_code        59
city              74
...

但是现在我想将它们中的每一个除以 test_set dataframe 中相应字段中不包含 NaN 的样本总数。我可以想到一些天真的方法来做到这一点,比如创建另一个列来保存不包含的数量每个列的 nan 值,但正在寻找一个漂亮的解决方案。

如果您不必合并,您可以使用:

import pandas as pd
import numpy as np

df1 = pd.DataFrame([
    ["1", "a"],
    ["2", np.NAN],
    ["3", "c"]
])

df2 = pd.DataFrame([
    ["1", "X"],
    ["100", "b"],
    ["3", "c"]
])

# expected:
# col 0: equal = 2, ratio: 2/3
# col 1: equal = 1, ratio: 1/2

df1 = df1.sort_index()
df2 = df2.sort_index()

def get_col_ratio(col):
    colA = df1[col]
    colB = df2[col]

    colA_ = colA[~(colA.isna() | colB.isna())]
    colB_ = colB[~(colA.isna() | colB.isna())]

    return (colA_.str.lower() == colB_.str.lower()).sum() / len(colA_)

ratios = pd.DataFrame([[get_col_ratio(i) for i in df1.columns]], columns=df1.columns)
print(ratios)

或者,使用pd.merge

fields = df1.columns
merged = pd.merge(df1,df2, left_index=True, right_index=True)

def get_ratio(col):
    cols = merged[[f"{col}_x",f"{col}_y"]]
    cols = cols.dropna()
    equal_rows = cols[cols.columns[0]].str.lower() == cols[cols.columns[1]].str.lower()
    return equal_rows.sum() / len(cols)

ratios = pd.DataFrame([[get_ratio(i) for i in fields]], columns=fields)
ratios

由于您有唯一的文件名,我会使用所有矢量操作,利用索引 alignment:

# set the filename as index
df1b = df1.set_index('file_name')
# set the filename as index
df2b = df2.set_index('file_name')

# compare and divide by the number of non-NA
out = df1b.eq(df2b).sum().div(df2b.notna().sum())

Output:

country_name    0.666667
dtype: float64

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM