【问题标题】:Dask datframe comparing two column and assigning the result (True,False) to another columnDask数据框比较两列并将结果(True,False)分配给另一列
【发布时间】:2021-08-22 00:56:37
【问题描述】:

我知道此类问题已被多次问过,但这些解决方案都没有帮助我。所以我为我的特殊情况发布了另一个。

我从 SQL 获取数据,数据框看起来像:

#for getting data from server
df1 = dd.read_sql_table(sa_query, connect_str, index_col=ind_col, columns=sa_columns)

#df1
 col1 col2  ...  coln
    1       ...     1
    2       ...     3
  2.3       ...     3
    3       ...     4

并使用 csv 文件:

#for reading csv file
df2 = dd.read_csv(file, low_memory=False, dtype=str)

#df2
 col1  col2 ...  coln
    1       ...     1
    2       ...     2
  2.3       ...     3
    4       ...     4

我正在合并两个数据框并创建一个新的 df,如下所示:

#df
 col1_df1 col1_df2 col2_df1 col2_df2 ... coln_df1 coln_df2
        1        1                   ...        1        1
        2        2                   ...        3        2
      2.3      2.3                   ...        3        3
        3        4                   ...        4        4

我检查过,df1 和 df2 中的所有列的类型均为 objectstring。某些列中可能包含 null 或没有值。我想要实现的是比较 col1_df1col2_df2 中的值,并使用比较的 True/False 值创建一个新列 col1_match

更新

我正在努力做到这一点:

if df[col1_df1].dtype.kind == df[col1_df2].dtype.kind:
    if df[col1_df1].dtype.kind == 'O':
        df[col1_match] = df[col1_df1].astype(str).fillna('') == df[col1_df2].astype(str).fillna('')
    elif df[col1_df1].dtype.kind == 'f':
        df[col1_match] = ((df[col1_df1] - df[col1_df2]).abs() <= 0)
    elif df[col1_df1].dtype.kind == 'i':
        df[col1_match] = ((df[col1_df1] - df[col1_df2]).abs() <= 0)
    else:
        df[col1_match] = df[col1_df1] == df[col1_df2]
else:
    print("does not match")
    df[col1_match] = df[col1_df1] == df[col1_df2]

这会产生

col1_df1 col1_df2 col2_df1 col2_df2 ... coln_df1 coln_df2 col1_match col2_match ... coln_match
        1        1                  ...        1        1       True      False           True
        2        2                  ...        3        2       True      False          False
      2.3      2.3                  ...        3        3       True      False           True
        3        4                  ...        4        4      False      False           True

它仍然为空值返回False

【问题讨论】:

  • 字符串的“非常接近”是什么意思?您想解释为浮点数并进行比较吗?
  • .02 差异并不重要。我的情况也是如此。但我无法将字符串列转换为浮点数。我尝试使用.astype(float),但它给了我错误

标签: python pandas pycharm dask dask-dataframe


【解决方案1】:

试试这个:

示例:

import pandas as pd
import numpy as np

df = pd.DataFrame({'A': [1,1.01,np.nan,np.nan], 'B':[1,1.02,np.nan,3]})

代码:

mask = (df['A'].astype(str) == df['B'].astype(str)) | ((df['A'] - df['B']).abs() <= 0.02)

df['col_1_match'] = mask

输出:

Out[13]: 
0     True
1     True
2     True
3    False
dtype: bool

说明:

nan == nan 总是错误的,但如果你事先将它转换为字符串,你可以比较它们,或者你可以在比较之前使用定义的值执行 .fillna()。至于差异,只需取值 1 分钟值 2 并比较差异是否小于您的阈值。

【讨论】:

  • nan == nan 总是错误的。谢谢你解释这个。我正在尝试您的解决方案,看看它是否对我的情况有帮助。
  • 我收到错误TypeError("unsupported operand type(s) for -: 'str' and 'str'
  • @bhakti123 这意味着您的列中有一些字符串,您只能计算字符串之间的差异,而不是字符串之间的差异。这就是为什么我根据整数值计算差异并根据它们的字符串检查 nan 值是否相同..
  • 但是如果我的列包含“2.34”和“2.3”作为字符串,那么我如何在这种情况下获得 True?
  • 尝试添加.astype(int).map(int)
【解决方案2】:

对于遇到此问题的任何人,我都能像这样解决它:

#for getting data from server
df1 = dd.read_sql_table(sa_query, connect_str, index_col=ind_col, columns=sa_columns)

#for reading csv file
df2 = dd.read_csv(file, low_memory=False, dtype=str)

#merging the data frames
params = {"on": join_columns}
outer_join = df1.merge(df2, how="outer", suffixes=("_df1", "_df2"), indicator=True, **params)
intersect_rows = outer_join[outer_join["_merge"] == "both"].copy()

#for getting True/False
for column in sorted(set(df1.columns) & set(df2.columns)):    
    intersect_rows = intersect_rows.map_partitions(map_compare, column)

def map_compare(df, column):
    try:
        df[column + "_match"] = np.isclose(df[column + "_df1"], df[column + "_df2"], rtol=0.005, atol=0.005, equal_nan=True)
    except TypeError:
        try:
            df[column + "_match"] = np.isclose(df[column + "_df1"].astype(float), df[column + "_df2"].astype(float), rtol=0.005, atol=0.005, equal_nan=True)
        except (ValueError, TypeError):
            try:
                df[column + "_match"] = (df[column + "_df1"] == df[column + "_df2"]) | (df[column + "_df1"].isnull() & df[column + "_df2"].isnull())
            except:
                df[column + "_match"] = np.equal(df[column + "_df1"].astype(str), df[column + "_df2"].astype(str))
    return df

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多