作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有人口统计面板数据,其中每个数据点按国家、性别、年份和年龄分类。对于给定的国家、性别和年份,我的年龄模式缺少数据,我想根据年龄值对其进行插值。例如,如果 5 岁 child 的值为 5,10 岁 child 的值为 10,则 6.3 岁 child 的值为 6.3。我不能使用默认的 Pandas “线性”插值方法,因为我的年龄组不是线性间隔的。我的数据看起来像这样:
iso3s = ['USA', 'CAN']
age_start_in_years = [0, 0.01, 0.1, 1]
years = [1990, 1991]
sexes = [1,2]
multi_index = pd.MultiIndex.from_product([iso3s,sexes,years,age_start_in_years],
names = ['iso3','sex','year','age_start'])
frame_length = len(iso3s)*len(age_start_in_years)*len(years)*len(sexes)
test_df = pd.DataFrame({'value':range(frame_length)},index=multi_index)
test_df=test_df.sortlevel()
# Insert missingness to practice interpolating
idx = pd.IndexSlice
test_df.loc[idx[:,:,:,[0.01,0.1]],:] = np.NaN
test_df
value
iso3 sex year age_start
CAN 1 1990 0.00 0
0.01 NaN
0.10 NaN
1.00 3
1991 0.00 4
0.01 NaN
0.10 NaN
1.00 7
2 1990 0.00 8
...
但是,当我尝试使用 test_df.interpolate(method='index')
时,出现此错误:
ValueError: Only `method=linear` interpolation is supported on MultiIndexes.
肯定有一些方法可以根据索引值进行插值。
最佳答案
这可能来得有点晚,但我今天遇到了同样的问题。我想出的也只是一个解决方法,但它至少使用了 pandas 内置函数。我的方法是重置索引,然后按索引列的第一个子集分组(即除 age_start
之外的所有列)。然后可以使用 method='index'
参数对这些子数据帧进行插值,并使用 pd.concat
将它们放回到一个完整的帧中。然后,生成的 DataFrame 会重新分配其原始索引。
idx_names = test_df.index.names
test_df = test_df.reset_index()
concat_list = [grp.set_index('age_start').interpolate(method='index') for _, grp in test_df.groupby(['iso3', 'sex', 'year'])]
test_df = pd.concat(concat_list)
test_df = test_df.reset_index().set_index(idx_names)
test_df
value
iso3 sex year age_start
CAN 1 1990 0.00 16.00
0.01 16.03
0.10 16.30
1.00 19.00
1991 0.00 20.00
0.01 20.03
0.10 20.30
1.00 23.00
2 1990 0.00 24.00
我今天回到这个问题上,发现我最初提出的解决方案中有一个错误。当多索引没有像您的示例中那样排序时,上面的代码按索引值对您的 DataFrame 进行排序。为了解决这个问题,我将结果加入到具有原始索引的 DataFrame 中,以便保留索引顺序。我还把它放在一个函数中。
def interp_multiindex(df, interp_idx_name):
"""
Provides index-based interpolation for pd.Multiindex which usually only support linear
interpolation. Interpolates full DataFrame.
Parameters
----------
df : pd.DataFrame
The DataFrame with NaN values
interp_idx_name : str
The name of the multiindex level on which index-based interpolation should take place
Returns
-------
df : pd.DataFrame
The DataFrame with index-based interpolated values
"""
# Get all index level names in order
existing_multiidx = df.index
# Remove the name on which interpolation will take place
noninterp_idx_names = [idx_name for idx_name in existing_multiidx.names
if idx_name != interp_idx_name]
df = df.reset_index()
concat_list = [grp.set_index(interp_idx_name).interpolate(method='index')
for _, grp in df.groupby(noninterp_idx_names)]
df = pd.concat(concat_list)
df = df.reset_index().set_index(existing_multiidx.names)
df = pd.DataFrame(index=existing_multiidx).join(df)
return df
关于python - 使用 pandas MultiIndex 时如何根据索引值进行插值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32496062/
我是一名优秀的程序员,十分优秀!