Numpy решение для замены только A
запускает столбцы:
#select only A starting columns
mask = df.columns.str.startswith('A')
df1 = df.loc[:, mask]
print (df1)
A.1.a A.3.d A.6.i
0 NaN 2.0 3.0
1 1.0 2.0 3.0
2 1.0 NaN 3.0
3 1.0 2.0 3.0
4 NaN 2.0 3.0
5 1.0 2.0 NaN
#convert to 2d array
arr = df1.values
#broadcast to 2d array by df1 shape
a = np.broadcast_to(np.nanmean(arr, axis=1)[:, None], df1.shape)
#check missing values
m = np.isnan(arr)
#replace them by mask
arr[m] = a[m]
print (arr)
[[2.5 2. 3. ]
[1. 2. 3. ]
[1. 2. 3. ]
[1. 2. 3. ]
[2.5 2. 3. ]
[1. 2. 1.5]]
#assign back
df.loc[:, mask] = arr
print (df)
A.1.a A.3.d A.6.i B.2.b
0 2.5 2.0 3.0 12
1 1.0 2.0 3.0 12
2 1.0 2.0 3.0 12
3 1.0 2.0 3.0 12
4 2.5 2.0 3.0 12
5 1.0 2.0 1.5 12
При необходимости замените NaN
s на группы, определенные первым значением столбцов:
df = df.combine_first(df.groupby(lambda x: x[0], axis=1).transform('mean'))
#alternative
#df = df.combine_first(df.groupby(df.columns.str[0], axis=1).transform('mean'))
print (df)
A.1.a A.3.d A.6.i B.2.b
0 2.5 2.0 3.0 12
1 1.0 2.0 3.0 12
2 1.0 2.0 3.0 12
3 1.0 2.0 3.0 12
4 2.5 2.0 3.0 12
5 1.0 2.0 1.5 12
Другая идея - создать словарь Series
и заменить его на DataFrame.fillna
:
df1 = df.groupby(df.columns.str[0], axis=1).mean()
df = df.fillna({x: df1[x[0]] for x in df.columns})
print (df)
A.1.a A.3.d A.6.i B.2.b
0 2.5 2.0 3.0 12
1 1.0 2.0 3.0 12
2 1.0 2.0 3.0 12
3 1.0 2.0 3.0 12
4 2.5 2.0 3.0 12
5 1.0 2.0 1.5 12