如何解决 ValueError:无法从重复轴重新索引

Posted

技术标签:

【中文标题】如何解决 ValueError:无法从重复轴重新索引【英文标题】:How to resolve ValueError: cannot reindex from a duplicate axis 【发布时间】:2021-10-03 23:21:53 【问题描述】:

输入

Client First name Last Name Start Date End Date Amount Invoice Date
XXX John Kennedy 15-01-2021 28-02-2021 137,586.00 20-04-2021
YYY Peter Paul 7-02-2021 31-03-2021 38,750.00 20-04-2021
ZZZ Michael K 10-03-2021 29-04-2021 137,586.00 30-04-2021

代码

df = pd.read_excel ('file.xlsx',parse_dates=['Start Date','End Date'] )
df['Start Date'] = pd.to_datetime(df['Start Date'],format='%d-%m-%Y')
df['End Date'] = pd.to_datetime(df['End Date'],format='%d-%m-%Y')

df['r'] = df.apply(lambda x: pd.date_range(x['Start Date'],x['End Date']), axis=1)
df = df.explode('r')
print(df)

months = df['r'].dt.month

starts, ends = months.ne(months.groupby(level=0).shift(1)), months.ne(months.groupby(level=0).shift(-1))


df2 = pd.DataFrame('First Name': df['First name'],
           'Start Date': df.loc[starts, 'r'].dt.strftime('%Y-%m-%d'),
                   'End Date': df.loc[ends, 'r'].dt.strftime('%Y-%m-%d'),
                   'Date Diff': df.loc[ends, 'r'].dt.strftime('%d').astype(int)-df.loc[starts, 'r'].dt.strftime('%d').astype(int)+1)

df = df.loc[~df.index.duplicated(), :]

df2 = pd.merge(df, df2, left_index=True, right_index=True)

df2['Amount'] = df['Amount'].mul(df2['Date_Diff'])
print(df['Amount'])
print (df)

df.to_excel('report.xlsx', index=True)

错误 ValueError:无法从重复的轴重新索引

预期输出

如何解决这个问题?

【问题讨论】:

这能回答你的问题吗? What does `ValueError: cannot reindex from a duplicate axis` mean? 【参考方案1】:

首先在您的输入 Excel 文件中进行一些更正,即更改名字First Name - 大写“N”,就像在其他列中一样。

然后,要读取您的 Excel 文件,运行就足够了:

df = pd.read_excel('Input.xlsx', parse_dates=['Start Date', 'End Date',
   'Invoice Date'], dayfirst=True)

无需调用to_datetime

还要注意,由于 Invoice Date 也包含日期,因此我将此列添加到 parse_dates 列表。

然后定义两个函数:

    获取当前行每月数据的函数:

    def getMonthData(grp, amnt, dayNo):
        return pd.Series([grp.min(), grp.max(), amnt * grp.size / dayNo],
            index=['Start Date', 'End Date', 'Amount'])
    

    它将输入的日期系列(单月)转换为“新”内容 输出行(开始/结束日期和总额的适当份额,要 占本月)。

    它将在以下函数中调用。

    一个“爆炸”当前行的函数:

    def rowExpl(row):
        ind = pd.date_range(row['Start Date'], row['End Date']).to_series()
        rv = ind.groupby(pd.Grouper(freq='M')).apply(getMonthData,
            amnt=row.Amount, dayNo=ind.size).unstack().reset_index(drop=True)
        rv.insert(0, 'Client', row.Client)
        rv.insert(1, 'First Name', row['First Name'])
        rv.insert(2, 'Last Name', row['Last Name'])
        return rv.assign(**'Invoice Date': row['Invoice Date'])
    

最后一步是得到结果。将 rowExpl 应用于每一行并连接 部分结果到单个输出 DataFrame 中:

result = pd.concat(df.apply(rowExpl, axis=1).values, ignore_index=True)

您的数据样本的结果是:

  Client First Name Last Name Start Date   End Date   Amount Invoice Date
0    XXX       John   Kennedy 2021-01-15 2021-01-31  51976.9   2021-04-20
1    XXX       John   Kennedy 2021-02-01 2021-02-28  85609.1   2021-04-20
2    YYY      Peter      Paul 2021-02-07 2021-02-28  16084.9   2021-04-20
3    YYY      Peter      Paul 2021-03-01 2021-03-31  22665.1   2021-04-20
4    ZZZ    Michael         K 2021-03-10 2021-03-31  59350.8   2021-04-30
5    ZZZ    Michael         K 2021-04-01 2021-04-29  78235.2   2021-04-30

不要对 Amount 列看似太低的精度感到不满。 这只是 Jupyter Notebook 显示 DataFrame 的方式。

当你运行result.iloc[0, 5],你会得到:

51976.933333333334

具有完整的、实际上保持的精确度。

【讨论】:

VaIdi_Bo 尝试执行该函数,但输出为空白 如果你执行了 result = pd.concat(…) 那么实际结果在 result 变量中。要查看此结果,请执行例如打印(结果)。还要检查文件名(这个文件是否实际包含预期的数据)。 另一项检查:不是从 Excel 文件中读取,而是从例如加载数据。 CSV 文件,然后执行我的代码。

以上是关于如何解决 ValueError:无法从重复轴重新索引的主要内容,如果未能解决你的问题,请参考以下文章

Pandas - ValueError:无法从重复的轴重新索引

ValueError:groupby Pandas 中的“无法从重复的轴重新索引”

Pandas - 在数据框中附加字符串:ValueError:无法从重复的轴重新索引

ValueError:无法使用 groupy 从重复轴重新索引并在 Pandas 中应用 pct_change

返回'无法从重复轴重新索引'…我在做什么错?

ValueError:无法将大小为 5 的序列复制到维度为 2 的数组轴