Pandas-添加重复年份的时间序列数据中缺失的年份

Pandas-Add missing years in time series data with duplicate years

我有一个这样的数据集,其中缺少几年的数据。

County Year Pop
12     1999 1.1
12     2001 1.2
13     1999 1.0
13     2000 1.1

我想要

County Year Pop
12     1999 1.1
12     2000 NaN
12     2001 1.2
13     1999 1.0
13     2000 1.1
13     2001 nan

我曾尝试将索引设置为年份,然后将 reindex 与另一个数据框的 just years 方法(此处提到 Pandas: Add data for missing months)一起使用,但它给了我错误 cant reindex with duplicate values。我也试过 df.loc 但它有同样的问题。我什至尝试过使用空白 df 进行完整的外部连接,但这也没有用。

我该如何解决这个问题?

创建一个 MultiIndex,这样您就不会重复:

df.set_index(['County', 'Year'], inplace=True)

然后构造一个包含所有组合的完整 MultiIndex:

index = pd.MultiIndex.from_product(df.index.levels)

然后重建索引:

df.reindex(index)

MultiIndex 的构造未经测试,可能需要稍作调整(例如,如果所有县都完全没有年份),但我想您明白了。

您可以使用 pivot_table:

In [11]: df.pivot_table(values="Pop", index="County", columns="Year")
Out[11]:
Year    1999  2000  2001
County
12       1.1   NaN   1.2
13       1.0   1.1   NaN

stack 结果(需要系列):

In [12]: df.pivot_table(values="Pop", index="County", columns="Year").stack(dropna=False)
Out[12]:
County  Year
12      1999    1.1
        2000    NaN
        2001    1.2
13      1999    1.0
        2000    1.1
        2001    NaN
dtype: float64

或者你可以尝试一些黑魔法:P

min_year, max_year = df.Year.min(), df.Year.max()

df.groupby('County').apply(lambda g: g.set_index("Year").reindex(range(min_year, max_year+1))).drop("County", axis=1).reset_index()

我的工作假设是您可能想要添加最小和最大年份之间的所有年份。可能是 1213.

两个县都缺少 2000

我将使用 'County' 列中的 unique 值和介于 pd.MultiIndex from_product 列中的所有整数年以及 'Year'列。

注意:此解决方案将填补所有缺失的年份,即使它们当前不存在。

mux = pd.MultiIndex.from_product([
        df.County.unique(),
        range(df.Year.min(), df.Year.max() + 1)
    ], names=['County', 'Year'])

df.set_index(['County', 'Year']).reindex(mux).reset_index()

   County  Year  Pop
0      12  1999  1.1
1      12  2000  NaN
2      12  2001  1.2
3      13  1999  1.0
4      13  2000  1.1
5      13  2001  NaN

您提到您曾尝试加入空白 df,这种方法确实可行。

设置:

df = pd.DataFrame({'County': {0: 12, 1: 12, 2: 13, 3: 13},
 'Pop': {0: 1.1, 1: 1.2, 2: 1.0, 3: 1.1},
 'Year': {0: 1999, 1: 2001, 2: 1999, 3: 2000}})

解决方案

#create a new blank df with all the required Years for each County
df_2 = pd.DataFrame(np.r_[pd.tools.util.cartesian_product([df.County.unique(),np.arange(1999,2002)])].T, columns=['County','Year'])

#Left join the new dataframe to the existing dataframe to populate the Pop values.
pd.merge(df_2,df,on=['Year','County'],how='left')
Out[73]: 
   County  Year  Pop
0      12  1999  1.1
1      12  2000  NaN
2      12  2001  1.2
3      13  1999  1.0
4      13  2000  1.1
5      13  2001  NaN

这是一个受已接受答案启发的函数,但针对 time-variable 在不同位置开始和停止不同组 ID 的情况。与接受的答案的唯一区别是我手动构建 multi-index.

def fill_gaps_in_panel(df, group_col, year_col):
    """
    Fills the gaps in a panel by constructing an index
    based on the group col and the sequence of years between min-year
    and max-year for each group id.
    """
    index_group = []
    index_time = []
    for group in df[group_col].unique():
        _min = df.loc[df[group_col]==group, year_col].min()
        _max = df.loc[df[group_col]==group, year_col].max() + 1
        index_group.extend([group for t in range(_min, _max)])
        index_time.extend([t for t in range(_min, _max)])
    multi_index = pd.MultiIndex.from_arrays(
        [index_group, index_time], names=(group_col, year_col))
    df.set_index([group_col, year_col], inplace=True)
    return df.reindex(multi_index)