Pandas 箱内的零填充
Zero padding inside of Pandas bins
我有一个 Pandas 数据框 df
,如下所示:
df = pd.DataFrame(data={"Group": ["a", "a", "a", "b", "b"],
"Index": [1, 8, 9, 1, 3],
"Value": [23.2, 1.2, 1.7, 21.9, 432.2]})
>>> print(df)
Group Index Value
0 a 1 23.2
1 a 8 1.2
2 a 9 1.7
3 b 1 21.9
4 b 3 432.2
我想获取以下信息(空行是为了说明):
Group Index Value
0 a 1 23.2
1 a 2 0.0
2 a 3 0.0
3 a 7 0.0
4 a 8 1.2
5 a 9 1.7
6 b 1 21.9
7 b 2 0.0
8 b 3 432.2
基本上我想在“值”列中引入零填充,以便所有“索引”容器 [1、2、3]、[4、5、6] 和 [7、8、9]恰好填充了 3 个值。 “Index”整数在组内只能出现一次,范围为 1 到 9。如果 bin 不包含任何“Index”整数,则不应进行填充。 “a组”和“b组”的行应该独立处理。
这是我得到的结果:
a_group = df.groupby("Group")
for _, group in a_group:
group["Bin"] = pd.cut(group["Index"], bins=list(range(1, 12, 3)), right=False)
print(group)
print("\n")
Group Index Value Bin
0 a 1 23.2 [1, 4)
1 a 8 1.2 [7, 10)
2 a 9 1.7 [7, 10)
Group Index Value Bin
3 b 1 21.9 [1, 4)
4 b 3 432.2 [1, 4)
此时我不知道还能做什么,希望能得到一些帮助。提前致谢。
这是您要找的吗?
g = df['Group'].unique()
i = range(1,df['Index'].max()+1)
df2 = df.set_index(['Group','Index']).reindex(pd.MultiIndex.from_product([g,i])).assign(cc = lambda x: (x.groupby(level=0).cumcount())//3).rename_axis(['Group','Index'],axis=0)
df2.loc[~df2['Value'].isna().groupby([pd.Grouper(level=0),df2['cc']]).transform('all')].reset_index().fillna(0).drop('cc',axis=1)
@rhug123 接受的答案是一个很好的答案,但我在下面提出了一个替代解决方案。我的解决方案的核心思想是创建一个 bin identifier/key 来帮助 select 目标索引。
TL;DR
max_index_value = 9
bin_size = 3
df_temp = pd.DataFrame({"Group":np.repeat(df['Group'].unique(), max_index_value)})
df_temp['Index'] = df_temp.groupby(['Group']).cumcount() + 1
df_temp = df_temp.merge(df, how='left', on=['Group', 'Index'])
df_temp['bin_key'] = df_temp.groupby(['Group']).cumcount() // bin_size
df_bin_key = df_temp.groupby(['Group', 'bin_key'])[['Value']].max().reset_index().dropna().drop(columns=['Value'])
df_final = df_bin_key.merge(df_temp, how='left', on=['Group', 'bin_key']).fillna(0).drop(columns=['bin_key'])
分步说明。
首先创建一个临时数据框,用作原始 df
.
缺失索引值的占位符
max_index_value = 9
bin_size = 3
df_temp = pd.DataFrame({"Group":np.repeat(df['Group'].unique(), max_index_value)})
df_temp['Index'] = df_temp.groupby(['Group']).cumcount() + 1
# getting the values from original dataset
df_temp = df_temp.merge(df, how='left', on=['Group', 'Index'])
接下来,添加用于标记 bin 以供稍后分组的 bin 键。
# the bin size defines the available key values
df_temp['bin_key'] = df_temp.groupby(['Group']).cumcount() // bin_size
Group Index bin_key Value
a 1 0 23.2
a 2 0 NaN
a 3 0 NaN
a 4 1 NaN
. . . .
. . . .
. . . .
b 6 1 NaN
b 7 2 NaN
b 8 2 NaN
b 9 2 NaN
然后,这是棘手的部分,我们在 Group
和 bin_key
列上使用组函数,并使用 max()
函数 select 哪个组和键应该出现在最终结果中。
df_bin_key = df_temp.groupby(['Group', 'bin_key'])[['Value']].max().reset_index().dropna().drop(columns=['Value'])
Group bin_key
a 0
a 2
b 0
最后,我们通过使用 Group
和 bin keys
.
将 df_temp
左连接到 df_bin_key
来达到预期的结果
df_final = df_bin_key.merge(df_temp, how='left', on=['Group', 'bin_key']).fillna(0).drop(columns=['bin_key'])
Group Index Value
a 1 23.2
a 2 0.0
a 3 0.0
a 7 0.0
a 8 1.2
a 9 1.7
b 1 21.9
b 2 0.0
b 3 432.2
PS:为了便于说明,我将这个解决方案分解为多个步骤,这里的一些步骤可以重写并组合成一行。
我有一个 Pandas 数据框 df
,如下所示:
df = pd.DataFrame(data={"Group": ["a", "a", "a", "b", "b"],
"Index": [1, 8, 9, 1, 3],
"Value": [23.2, 1.2, 1.7, 21.9, 432.2]})
>>> print(df)
Group Index Value
0 a 1 23.2
1 a 8 1.2
2 a 9 1.7
3 b 1 21.9
4 b 3 432.2
我想获取以下信息(空行是为了说明):
Group Index Value
0 a 1 23.2
1 a 2 0.0
2 a 3 0.0
3 a 7 0.0
4 a 8 1.2
5 a 9 1.7
6 b 1 21.9
7 b 2 0.0
8 b 3 432.2
基本上我想在“值”列中引入零填充,以便所有“索引”容器 [1、2、3]、[4、5、6] 和 [7、8、9]恰好填充了 3 个值。 “Index”整数在组内只能出现一次,范围为 1 到 9。如果 bin 不包含任何“Index”整数,则不应进行填充。 “a组”和“b组”的行应该独立处理。
这是我得到的结果:
a_group = df.groupby("Group")
for _, group in a_group:
group["Bin"] = pd.cut(group["Index"], bins=list(range(1, 12, 3)), right=False)
print(group)
print("\n")
Group Index Value Bin
0 a 1 23.2 [1, 4)
1 a 8 1.2 [7, 10)
2 a 9 1.7 [7, 10)
Group Index Value Bin
3 b 1 21.9 [1, 4)
4 b 3 432.2 [1, 4)
此时我不知道还能做什么,希望能得到一些帮助。提前致谢。
这是您要找的吗?
g = df['Group'].unique()
i = range(1,df['Index'].max()+1)
df2 = df.set_index(['Group','Index']).reindex(pd.MultiIndex.from_product([g,i])).assign(cc = lambda x: (x.groupby(level=0).cumcount())//3).rename_axis(['Group','Index'],axis=0)
df2.loc[~df2['Value'].isna().groupby([pd.Grouper(level=0),df2['cc']]).transform('all')].reset_index().fillna(0).drop('cc',axis=1)
@rhug123 接受的答案是一个很好的答案,但我在下面提出了一个替代解决方案。我的解决方案的核心思想是创建一个 bin identifier/key 来帮助 select 目标索引。
TL;DR
max_index_value = 9
bin_size = 3
df_temp = pd.DataFrame({"Group":np.repeat(df['Group'].unique(), max_index_value)})
df_temp['Index'] = df_temp.groupby(['Group']).cumcount() + 1
df_temp = df_temp.merge(df, how='left', on=['Group', 'Index'])
df_temp['bin_key'] = df_temp.groupby(['Group']).cumcount() // bin_size
df_bin_key = df_temp.groupby(['Group', 'bin_key'])[['Value']].max().reset_index().dropna().drop(columns=['Value'])
df_final = df_bin_key.merge(df_temp, how='left', on=['Group', 'bin_key']).fillna(0).drop(columns=['bin_key'])
分步说明。
首先创建一个临时数据框,用作原始 df
.
max_index_value = 9
bin_size = 3
df_temp = pd.DataFrame({"Group":np.repeat(df['Group'].unique(), max_index_value)})
df_temp['Index'] = df_temp.groupby(['Group']).cumcount() + 1
# getting the values from original dataset
df_temp = df_temp.merge(df, how='left', on=['Group', 'Index'])
接下来,添加用于标记 bin 以供稍后分组的 bin 键。
# the bin size defines the available key values
df_temp['bin_key'] = df_temp.groupby(['Group']).cumcount() // bin_size
Group Index bin_key Value
a 1 0 23.2
a 2 0 NaN
a 3 0 NaN
a 4 1 NaN
. . . .
. . . .
. . . .
b 6 1 NaN
b 7 2 NaN
b 8 2 NaN
b 9 2 NaN
然后,这是棘手的部分,我们在 Group
和 bin_key
列上使用组函数,并使用 max()
函数 select 哪个组和键应该出现在最终结果中。
df_bin_key = df_temp.groupby(['Group', 'bin_key'])[['Value']].max().reset_index().dropna().drop(columns=['Value'])
Group bin_key
a 0
a 2
b 0
最后,我们通过使用 Group
和 bin keys
.
df_temp
左连接到 df_bin_key
来达到预期的结果
df_final = df_bin_key.merge(df_temp, how='left', on=['Group', 'bin_key']).fillna(0).drop(columns=['bin_key'])
Group Index Value
a 1 23.2
a 2 0.0
a 3 0.0
a 7 0.0
a 8 1.2
a 9 1.7
b 1 21.9
b 2 0.0
b 3 432.2
PS:为了便于说明,我将这个解决方案分解为多个步骤,这里的一些步骤可以重写并组合成一行。