Я хочу переназначить значения в определенных строках и различных многоиндексных столбцах большого кадра данных pandas, df, на значения, отличные от NaN, которые были рассчитаны и сохранены в немного меньшем замаскированном подмножестве кадра данных, df_sub.
df =
A B
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 -51.0 -50.0 -49.0 -48.0 -47.0 -46.0 -45.0 -44.0 -43.0 -42.0
1 11.0 12.0 13.0 14.0 15.0 16.0 17.0 18.0 19.0 20.0 -41.0 -40.0 -39.0 -38.0 -37.0 -36.0 -35.0 -34.0 -33.0 -32.0
2 21.0 22.0 23.0 24.0 25.0 26.0 27.0 28.0 29.0 30.0 -31.0 -30.0 -29.0 -28.0 -27.0 -26.0 -25.0 -24.0 -23.0 -22.0
3 31.0 32.0 33.0 34.0 35.0 36.0 37.0 38.0 39.0 40.0 -21.0 -20.0 -29.0 -28.0 -27.0 -26.0 -25.0 -24.0 -23.0 -22.0
4 41.0 42.0 43.0 44.0 45.0 46.0 47.0 48.0 49.0 50.0 -11.0 -10.0 -9.0 -8.0 -7.0 -6.0 -5.0 -4.0 -3.0 -2.0
df_sub =
0 1 2 3 4 5 6 7 8 9
1 NaN NaN NaN NaN NaN 0.3 0.2 0.1 NaN NaN
3 NaN NaN NaN 0.6 0.9 0.7 NaN NaN NaN NaN
Моя цель - получить результат, показанный ниже, для df.loc [:, 'B'], где ненулевые значения в df_sub заменяют соответствующую строку и столбцы df (i.e., df.loc[1, pd.IndexSlice['B', 5:7]] = df_sub.loc[1, 5:7] and df.loc[3, pd.IndexSlice['B', 3:5]] = df_sub.loc[3, 3:5])
:
df.loc[:,'B'] =
0 1 2 3 4 5 6 7 8 9
0 -51.0 -50.0 -49.0 -48.0 -47.0 -46.0 -45.0 -44.0 -43.0 -42.0
1 -41.0 -40.0 -39.0 -38.0 -37.0 0.3 0.2 0.1 -33.0 -32.0
2 -31.0 -30.0 -29.0 -28.0 -27.0 -26.0 -25.0 -24.0 -23.0 -22.0
3 -21.0 -20.0 -19.0 0.6 0.9 0.7 -15.0 -14.0 -13.0 -12.0
4 -11.0 -10.0 -9.0 -8.0 -7.0 -6.0 -5.0 -4.0 -3.0 -2.0
Однако, получая желаемые значения, я получаю NaNs:
df.loc[:,'B'] =
0 1 2 3 4 5 6 7 8 9
0 -51.0 -50.0 -49.0 -48.0 -47.0 -46.0 -45.0 -44.0 -43.0 -42.0
1 -41.0 -40.0 -39.0 -38.0 -37.0 NaN NaN NaN -33.0 -32.0
2 -31.0 -30.0 -29.0 -28.0 -27.0 -26.0 -25.0 -24.0 -23.0 -22.0
3 -21.0 -20.0 -19.0 NaN NaN NaN -15.0 -14.0 -13.0 -12.0
4 -11.0 -10.0 -9.0 -8.0 -7.0 -6.0 -5.0 -4.0 -3.0 -2.0
Мой простой пример кода приведен ниже. Исходя из диагностики, похоже, что все ведет себя так, как ожидалось: 1) значения non-nan и их индексы из df_sub определены для каждой строки df_sub, 2) срезы исходного df кажутся правильными, и 3) назначение выполняется без претензий и предупреждений «установка копии».
- Как лучше всего достичь моей цели?
- Почему это не получается?
- Есть ли более компактный и эффективный способ выполнения заданий?
Упрощенный пример:
# Create data for example case
idf = pd.MultiIndex.from_product([['A', 'B'], np.arange(0,10)])
df = pd.DataFrame(np.concatenate((np.arange(1.,51.).reshape(5,10),
np.arange(-51., -1.).reshape(5,10)), axis=1),
index=np.arange(0,5), columns=idf)
df_sub = pd.DataFrame([[np.nan, np.nan, np.nan, np.nan, np.nan, 0.5, 0.6, 0.7, np.nan, np.nan],
[np.nan, np.nan, np.nan, 0.3, 0.4, 0.5, np.nan, np.nan, np.nan, np.nan]],
index=[1,3], columns=np.arange(0,10))
dfsub_idx = df_sub.index
# Perform assignments
for (idx, row) in df_sub.iterrows() :
arr = row.index[~row.isnull()]
print 'row {}: \n{}'.format(idx, row)
print 'non-nan indices: {}\n'.format(arr)
print 'df before mod: \n{}'.format(df.loc[idx, pd.IndexSlice['B', arr.tolist()]])
df.loc[idx, pd.IndexSlice['B', arr.tolist()]] = row[arr]
print 'df after mod: \n{}'.format(df.loc[idx, pd.IndexSlice['B', arr.tolist()]])