为啥合并不相等匹配的行不适用于本地数据集?

Posted

技术标签:

【中文标题】为啥合并不相等匹配的行不适用于本地数据集?【英文标题】:Why does merging unequally matched rows not work on local dataset?为什么合并不相等匹配的行不适用于本地数据集? 【发布时间】:2021-10-28 01:34:27 【问题描述】:

我有一个带有问题 (type = 1) 和答案 (type = 2) 的熊猫 dataframe。 col section_idtype 是整数。所有其他 col 都是字符串。在将一些答案行的值作为额外列(Ansans_t)附加到相应的“问题”之前,我想将“答案行”与其相应的“问题行”(section_id 中的相等值)合并行”。

c = ['pos', 'Ans', 'Q_ID', 'leg', 'que_l', 'ans_l', 'par', 'ans_f', 'que_date', 'ask', 'M_ID', 'part', 'area', 'que_t', 'ans_t', 'ISO', 'con', 'id', 'section_id', 'type', 'dep', 'off']
d = [[None, None, '16-17/1/2017-11-15/1', '16-17', '14.0', None, 'aaa', 'hhh', '2016-11-20', 'Peter Muller', '41749', 'bbb', 'ccc', 'ddd', None, 'eee', 'fff', '111865.q2', 24339851, 1, None, None],
     [None, None, '16-17/24/17-11-09/1', '16-17', '28.0', None, 'aaa', 'hhh', '2016-11-20', 'Peter Muller', '41749', 'bbb', 'ccc', 'ppp', None, 'eee', 'fff', '111867.q1', 24339851, 1, None, None],
     [None, None, '16-17/73/17-10-09/1', '16-17', '69.0', None, 'aaa', 'hhh', '2016-11-20', 'Peter Muller', '41749', 'bbb', 'ccc', 'lll', None, 'eee', 'fff', '111863.r0', 24339851, 1, None, None],
     ['erg', 'wer', '16-17/42/16-10-09/1', '16-17', None, 67.0, 'aaa', 'hhh', '2016-11-20', None, '46753', 'bbb', 'ccc', None, 'ttt', 'eee', 'asd', '111863.r0', 24339851, 2, None, None],
     [None, None, '16-17/12/16-12-08/1', '16-17', '37.0', None, 'aaa', 'hhh', '2016-10-10', 'Peter Muller', '41749', 'bbb', 'qqq', 'rrr', None, 'eee', 'fff', '108143.r0', 24303320, 1, None, None],
     ['erg', 'wer', '16-17/12/16-12-07/1', '16-17', None, 64.0, 'aaa', 'hhh', '2016-10-10', None, '46753', 'bbb', 'qqq', None, 'uuu', 'eee', 'asd', '108143.r0', 24303320, 2, None, None],
     [None, None, '16-17/77/16-12-04/1', '16-17', '46.0', None, 'aaa', 'hhh', '2016-10-08', 'Markus John', '34567', 'ztr', 'yyy', 'nnn', None, 'eee', 'www', '127193.q0', 10343145, 1, None, None],
     ['qwe', 'wer', '16-17/37/17-11-07/1', '16-17', None, 60.0, 'aaa', 'hhh', '2016-12-12', None, '19745', 'bbb', 'gtt', None, 'ooo', 'eee', 'asd', '906213.r0', 23222978, 2, None, None]]
data = pd.DataFrame(d,columns=c)
data.loc[data['type'] == 2, 'Ans.1'] = data['Ans']
data.loc[data['type'] == 2, 'ans_t.1'] = data['ans_t']
my_cols = ['que_t','ans_t','Ans','ans_t','Ans.1','ans_t.1']
data[my_cols] = data.sort_values(['section_id','type']).groupby('section_id')[my_cols].transform(lambda x: x.bfill())
data.dropna(subset=['que_t'],inplace=True)
data.reset_index(drop=True,inplace=True)
print(data)

代码在最小的可重现示例上运行良好。不幸的是,数据集太大而无法解释每个细节,这就是为什么这个例子不一定具有代表性。

问题:当我在实际数据集上运行代码时,没有任何东西被合并,即使我手动检查了 section_id 重复项

在执行代码之前,我从数据集中删除空单元格

data.where(pd.notnull(data), None)
data.replace(r'^\s+$', np.nan, regex=True, inplace=True)

解决不了问题

问题:我需要如何调整我的代码以考虑数据集中可能导致其不合并的细节(例如编码、格式等)?

附录:

有人告诉我逐渐从数据集中删除数据,每次检查测试用例是否仍然可重现。如果某些删除导致测试用例不起作用,则恢复它并删除其他内容。当绝对没有可以删除的内容时,您就拥有了最小的数据集。

有人说我应该应用解析函数来解析数据。没有帮助

def parse(x):
try:
    return int(x)
except ValueError:
    return np.nan
data['que_t'] = data['que_t'].apply(parse)
data['ans_t'] = data['ans_t'].apply(parse)
data.dtypes

或者我应该搜索非数字字符串并将 when 替换为 NaN 吗?

replaced_with_nan = data['col_name'].replace(re.compile('\D+'), np.nan)
data['col_name'] = replaced_with_nan.astype(np.float)

这是另一种方法,类似于 Andrej Kesely 的答案,在实际数据帧上使用时返回一个空数据帧

df1 = data.loc[df.type == 1].copy()
df2 = data.loc[df.type == 2].copy()
merged_df = pd.merge(df1, df2, on='section_id', how='outer')
merged_df = merged_df.loc[:,['section_id','que_t_x','ans_t_y','Ans_x','Ans_y']]
merged_df.rename(columns='que_t_x':'que_t','ans_t_y':'ans_t','Ans_x':'Ans','Ans_y':'Ans.1', inplace=True)

【问题讨论】:

您的代码不可重现检查data[my_cols] = data.sort_values(...这一行 你好。它是可重现的。它有效。但不在实际数据集上。 @id345678 您的问题描述中的代码存在错误,因此无法重现。该错误在以下行中:my_cols = ['que_t','ans_t','Ans','ans_t','Ans.1','ans_t.1']。有两个ans_ts,导致错误。 【参考方案1】:

如果我对您的理解正确,您可以过滤数据框并执行.merge:

x = (
    df[df["que/ans"] == 1]
    .merge(
        df[df["que/ans"] == 2],
        on="section_id",
        how="outer",
        suffixes=("_que", "_ans"),
    )
    .drop(columns=["ans_t_que", "name_que", "ans_len_que", "que_t_ans"])
)
print(x)

打印:

   que/ans_que  section_id que_t_que  date_que part_que  que/ans_ans ans_t_ans name_ans  date_ans part_ans  ans_len_ans
0            1         444    qtext1       456      bbb          2.0    atext2   Markus     654.0      eee         64.0
1            1         444    qtext3       987      ddd          2.0    atext2   Markus     654.0      eee         64.0
2            1         123    qtext2       789      ccc          2.0    atext1     Alex     123.0      aaa         78.0
3            1         555    qtext4       321      fff          NaN       NaN      NaN       NaN      NaN          NaN

【讨论】:

感谢您的回答。我看到你在那里做了什么,但收到一个空的数据框,合并后实际上应该有大约 5000 行。从列的名称来看,我认为您正确理解了我,这也有效,但我怀疑问题是某些单元格实际上不是 NaN,而是 None 或“空”?此外,还有一个日期列不在日期时间中,而是在对象 dtype 中。这会导致问题吗?我更新了我的问题以提供调试日志【参考方案2】:

如果您从 csv 或 excel 读取数据,我建议您在读取期间定义 dtype。这是为了确保您用于合并的密钥没有任何数据丢失。

示例: section_id = 00001234 从 csv 读取后,它可能只是 1234。

df = pd.read_csv(filename, dtype='section_id' = str)

希望这能解决您的合并问题。

【讨论】:

我从 json 文件中检索它,并通过在合并之前确保字符串类型来尝试它,但没有帮助。不过谢谢你的想法:) @id345678 既然您认为 NaN 或“空”会导致问题,为什么不在合并之前尝试 fillna(-999) 并从那里修复代码?从 Andrej Kesely 代码中,它将为您提供没有很好合并的行,这是检查问题的良好开端。【参考方案3】:

您在 Andrej 的回答之后的最后一个解决方案似乎有效。但是,有一些关于 df 变量的上下文缺失。此外,所有反映空虚的字符串都替换为np.nan。因此,我将其重写为data,如下所示:

data.replace(['', 'None', 'nan', None], np.nan, inplace=True)
df1 = data.loc[data.type == 1].copy()
df2 = data.loc[data.type == 2].copy()
merged_df = pd.merge(df1, df2, on='section_id', how='outer')
merged_df = merged_df[['section_id','que_t_x','ans_t_y','Ans_x','Ans_y']]
merged_df.rename(columns='que_t_x':'que_t','ans_t_y':'ans_t','Ans_x':'Ans','Ans_y':'Ans.1', inplace=True)
print(merged_df)

【讨论】:

以上是关于为啥合并不相等匹配的行不适用于本地数据集?的主要内容,如果未能解决你的问题,请参考以下文章

雪花 python 连接器不适用于 AWS Lambda 中的更大数据集

如何匹配不相等的数据集和不明确的常用术语?

数据步骤/SQL 连接/合并/联合 2 数据集/表并删除相同的行/观察

合并具有部分匹配值的行

即使我的变量相同,为啥我的行不会合并?

在 R 中匹配和合并具有不同列名的数据集