Python 修复数据帧

Python 修复数据帧,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个完整的案例+20k的输入_df,它被测试并转换为输出_df 输入的一些情况失败,然后我们在输出上得到失败的输出。 如果是这种情况,我们需要修复旧的输入,并重新生成新的输入。 因此,我们寻求的最终结果是新的输入 我们解决这个问题的方法是简单地更改失败案例的输入日期。 我们知道由于输出结果列中的输出失败或成功而失败的案例 下面的示例-实际df超过20k行 即: 输出功率 case_id output_date carBrand ouput_result 1

我有一个完整的案例+20k的输入_df,它被测试并转换为输出_df

输入的一些情况失败,然后我们在输出上得到失败的输出。 如果是这种情况,我们需要修复旧的输入,并重新生成新的输入。 因此,我们寻求的最终结果是新的输入 我们解决这个问题的方法是简单地更改失败案例的输入日期。 我们知道由于输出结果列中的输出失败或成功而失败的案例

下面的示例-实际df超过20k行 即:

输出功率

case_id        output_date        carBrand     ouput_result
1                 01/20/21             001          FAIL
2                 02/21/21             002          SUCCESS  
3                 02/08/20             003          FAIL 
4                 01/07/20             001          FAIL
5                 09/05/20             002          SUCCESS
输入旧数据

case_id    input_date         carBrand 
    1          01/20/21             001  
    2          02/21/21             002 
    3          02/08/20             003
    4          01/07/20             001
    5          09/05/20             002
修复更改日期后的新预期结果=>

输入新的

case_id   input_date              carBrand 
    **1          01/13/21             001**  
    2          02/21/21             002 
    **3          02/22/20             003**
    **4          01/28/20             001**
    5          09/05/20             002
输入和输出具有匹配的列大小写id。 我们需要做以下工作

从输出中获取状态为FAIL的行case\u id

使用case\u id将这些行与输入中的行匹配 例如,上面我们看到案例1、3、4失败。因此,我们转到输入_df并查找 第1、3、5行。 =>失败是因为日期错误;因此,我们需要在+-7天内选择一个新日期 是旧的数倍。因此,如果原始输入的旧日期为2020年1月20日,则为新测试日期 我们可以选择2020年1月27日 或另一个+-7天的倍数。ie:14,21,28,35

现在,我们需要做一个groupByinput\u carID,即:inputID是一组案例。 我们这样做是因为我们需要通过不在组级别引入重复值来修复这些情况。 把这想象成一个美塞德斯集团,或者福特、迈凯轮等的集团。。。 因此,当我们为失败案例选择新的日期时,我们需要检查特定组中的所有案例 我们选择的日期之前尚未选择。 =>因此,我们对每个汽车品牌groupBy进行分组,然后修复每组失败的案例

当我们检查了每个组中的所有失败案例后,我们现在有了一个新的输入

修复方法是将输入中的日期更改为旧,从而获得新的输入 到目前为止,这是我所拥有的,但不起作用。我没有得到唯一的输入值,而且由于某些原因,输入值被打印了3次

    import pandas as pd
    import numpy as np
    import datetime
    
    output_df = pd.DataFrame(
    {
    "case_id": [1, 2, 3, 4, 5],
    "output_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
    "output_carId": ["001", "001", "003", "001", "002"],
    "output_result": ["FAIL", "SUCCESS", "FAIL", "FAIL", "SUCCESS"],
    },
    columns=["case_id", "output_date", "output_carId", "output_result"],
    )
    input_df = pd.DataFrame(
    {
    "case_id": [1, 2, 3, 4, 5],
    "input_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
    "input_carId": ["001", "001", "003", "001", "002"],
    },
    columns=["case_id", "input_date", "input_carId"],
    )
    
 
    
    def func(x, old_input):
    # print(old_input)
    mask = x['output_result'] == 'FAIL'
    count = mask.sum()
    indexes = x.loc[mask]
    # print(indexes.index)
    arr = np.arange(1, count + 1) * 7
    np.random.shuffle(arr)
    td = pd.to_timedelta(arr, unit='d')
    old_input.loc[indexes.index, 'input_date'] = pd.to_datetime(old_input.loc[indexes.index, 'input_date']) + td
    old_input.loc[indexes.index, 'input_date'] = pd.to_datetime(old_input.loc[indexes.index, 'input_date']).dt.date
    return old_input
    
    
    **new_input** = output_df.groupby('output_carId').apply(lambda x: func(x, input_df))
    print(new_input)

 

在groupby的每次迭代中,您都返回一个完整的数据帧。你能用这个吗?独立运行函数中的内容,而不是执行groupby

output_df = pd.DataFrame(
    {
    "case_id": [1, 2, 3, 4, 5],
    "output_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
    "output_carId": ["001", "001", "003", "001", "002"],
    "output_result": ["FAIL", "SUCCESS", "FAIL", "FAIL", "SUCCESS"],
    },
    columns=["case_id", "output_date", "output_carId", "output_result"],
    )

input_df = pd.DataFrame(
    {
    "case_id": [1, 2, 3, 4, 5],
    "input_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
    "input_carId": ["001", "001", "003", "001", "002"],
    },
    columns=["case_id", "input_date", "input_carId"],
    )

mask = output_df['output_result'] == 'FAIL'
count = mask.sum()
indexes = output_df.loc[mask]
# print(indexes.index)
arr = np.arange(1, count + 1) * 7
np.random.shuffle(arr)
td = pd.to_timedelta(arr, unit='d')
old_input = input_df
old_input.loc[indexes.index, 'input_date'] = pd.to_datetime(old_input.loc[indexes.index, 'input_date']) + td
old_input.loc[indexes.index, 'input_date'] = pd.to_datetime(old_input.loc[indexes.index, 'input_date']).dt.date
old_input
这是新的“旧输出”,我不确定我是否理解你的命名文化。。。。。请原谅来自jupyter笔记本的格式设置

case_id input_date  input_carId
0   1   2021-02-03  001
1   2   2021-02-21  001
2   3   2020-02-29  003
3   4   2020-01-14  001
4   5   2020-09-05  002

在groupby的每次迭代中,您都返回一个完整的数据帧。你能用这个吗?独立运行函数中的内容,而不是执行groupby

output_df = pd.DataFrame(
    {
    "case_id": [1, 2, 3, 4, 5],
    "output_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
    "output_carId": ["001", "001", "003", "001", "002"],
    "output_result": ["FAIL", "SUCCESS", "FAIL", "FAIL", "SUCCESS"],
    },
    columns=["case_id", "output_date", "output_carId", "output_result"],
    )

input_df = pd.DataFrame(
    {
    "case_id": [1, 2, 3, 4, 5],
    "input_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
    "input_carId": ["001", "001", "003", "001", "002"],
    },
    columns=["case_id", "input_date", "input_carId"],
    )

mask = output_df['output_result'] == 'FAIL'
count = mask.sum()
indexes = output_df.loc[mask]
# print(indexes.index)
arr = np.arange(1, count + 1) * 7
np.random.shuffle(arr)
td = pd.to_timedelta(arr, unit='d')
old_input = input_df
old_input.loc[indexes.index, 'input_date'] = pd.to_datetime(old_input.loc[indexes.index, 'input_date']) + td
old_input.loc[indexes.index, 'input_date'] = pd.to_datetime(old_input.loc[indexes.index, 'input_date']).dt.date
old_input
这是新的“旧输出”,我不确定我是否理解你的命名文化。。。。。请原谅来自jupyter笔记本的格式设置

case_id input_date  input_carId
0   1   2021-02-03  001
1   2   2021-02-21  001
2   3   2020-02-29  003
3   4   2020-01-14  001
4   5   2020-09-05  002

在这里,你为什么使用groupby?它是不需要使用的。 虽然数据帧很大,但首先会使用掩码,因此不会有问题

output_df = pd.DataFrame(
    {
        "case_id": [1, 2, 3, 4, 5],
        "output_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
        "output_carId": ["001", "001", "003", "001", "002"],
        "output_result": ["FAIL", "SUCCESS", "FAIL", "FAIL", "SUCCESS"],
    },
    columns=["case_id", "output_date", "output_carId", "output_result"]
)

input_df = pd.DataFrame(
    {
        "case_id": [1, 2, 3, 4, 5],
        "input_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
        "input_carId": ["001", "001", "003", "001", "002"],
    },
    columns=["case_id", "input_date", "input_carId"]
)

def func(x, old_input):
    mask = x['output_result'] == 'FAIL'
    count = mask.sum()
    if count == 0:
        return old_input
    indexes = x.loc[mask]
    while True:
        arr = np.arange(1, count + 1) * 7
        np.random.shuffle(arr)
        td = pd.to_timedelta(arr, unit='d')
        delta_date = pd.to_datetime(old_input.loc[indexes.index, 'input_date']) + td
        delta_date = pd.to_datetime(delta_date).dt.strftime("%Y-%m-%d")
        old_input.loc[indexes.index, 'input_date'] = delta_date
        new_dates = delta_date.unique()
        old_dates = old_input['input_date'].unique()
        if np.any(np.in1d(new_dates, old_dates)):
            break
    return old_input

group_by = output_df.groupby('output_carId', group_keys=False)
input_len = input_df.__len__()
group_len = group_by.groups.__len__()
apply_input = group_by.apply(lambda x: func(x, input_df))
new_input = apply_input[input_len * (group_len - 1):input_len * group_len]
print(new_input)
结果是

   case_id  input_date input_carId
0        1  2021-02-03         001
1        2  2021-02-21         001
2        3  2020-02-15         003
3        4  2020-01-28         001
4        5  2020-09-05         002

在这里,你为什么使用groupby?它是不需要使用的。 虽然数据帧很大,但首先会使用掩码,因此不会有问题

output_df = pd.DataFrame(
    {
        "case_id": [1, 2, 3, 4, 5],
        "output_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
        "output_carId": ["001", "001", "003", "001", "002"],
        "output_result": ["FAIL", "SUCCESS", "FAIL", "FAIL", "SUCCESS"],
    },
    columns=["case_id", "output_date", "output_carId", "output_result"]
)

input_df = pd.DataFrame(
    {
        "case_id": [1, 2, 3, 4, 5],
        "input_date": ["2021-01-20", "2021-02-21", "2020-02-08", "2020-01-07", "2020-09-05"],
        "input_carId": ["001", "001", "003", "001", "002"],
    },
    columns=["case_id", "input_date", "input_carId"]
)

def func(x, old_input):
    mask = x['output_result'] == 'FAIL'
    count = mask.sum()
    if count == 0:
        return old_input
    indexes = x.loc[mask]
    while True:
        arr = np.arange(1, count + 1) * 7
        np.random.shuffle(arr)
        td = pd.to_timedelta(arr, unit='d')
        delta_date = pd.to_datetime(old_input.loc[indexes.index, 'input_date']) + td
        delta_date = pd.to_datetime(delta_date).dt.strftime("%Y-%m-%d")
        old_input.loc[indexes.index, 'input_date'] = delta_date
        new_dates = delta_date.unique()
        old_dates = old_input['input_date'].unique()
        if np.any(np.in1d(new_dates, old_dates)):
            break
    return old_input

group_by = output_df.groupby('output_carId', group_keys=False)
input_len = input_df.__len__()
group_len = group_by.groups.__len__()
apply_input = group_by.apply(lambda x: func(x, input_df))
new_input = apply_input[input_len * (group_len - 1):input_len * group_len]
print(new_input)
结果是

   case_id  input_date input_carId
0        1  2021-02-03         001
1        2  2021-02-21         001
2        3  2020-02-15         003
3        4  2020-01-28         001
4        5  2020-09-05         002

谢谢我会查的你能查一下唯一的部分吗现在我们不确定每个组的日期是否唯一。嗨,@Song的解决方案有效吗?如果是这样的话,请将答案标记为正确。答案是正确的,但需要你的帮助!谢谢我会查的你能查一下唯一的部分吗现在我们不确定每个组的日期是否唯一。嗨,@Song的解决方案有效吗?如果是这样的话,请将答案标记为正确。答案是正确的,但需要你的帮助!15行表示重复打印结果。也许,当函数中的最后一个组从组索引返回时,返回会很好,谢谢;但问题是,我需要检查每个失败案例组中的唯一日期。目前,该解决方案仅将行添加到输入数据框,然后itI更新为唯一日期,重复数据框打印15行表示重复打印结果。也许,当函数中的最后一个组从组索引返回时,返回会很好,谢谢;但问题是,我需要检查每个失败案例组中的唯一日期。目前,此解决方案仅将行添加到输入数据框,然后itI将更新为唯一日期和重复数据框打印