Как я могу установить значение ряда в определенном в цепочечном стиле?

#python #pandas #method-chaining

#python #панды #метод-цепочка

Вопрос:

Я не могу понять, как установить значение ряда по определенному индексу в цепочечном стиле.

Например, скажем, у меня есть следующий фрейм данных:

 >>> df = pd.DataFrame({'a': [1,2,3], 'b': [0,0,0]})
>>> df
   a  b
0  1  0
1  2  0
2  3  0
 

Если я хочу изменить все значения столбца в конвейере, я могу использовать pandas.DataFrame.assign() :

 >>> df.assign(b=[4,5,6])
   a  b
0  1  4
1  2  5
2  3  6
 

… и тогда я могу делать другие вещи с фреймом данных в той же строке, например:

 >>> df.assign(b=[4,5,6]).mul(100)
     a    b
0  100  400
1  200  500
2  300  600
 

Но я не могу сделать это для отдельного значения в определенном в серии.

 >>> s = df['a']
>>> s
0    1
1    2
2    3
Name: a, dtype: int64
 

Я могу, конечно, просто использовать обычную операцию присваивания Python, используя = :

 >>> s[1] = 9
>>> s
0    1
1    9
2    3
Name: a, dtype: int64
 

Но проблемы с этим заключаются в:

  • Он на месте, поэтому он изменяет мой существующий фрейм данных
  • Использование операторов присваивания = не допускается в лямбда-функциях Python

Например, что, если бы я хотел сделать это:

 >>> df.apply(lambda x: x['b', 0] = 13, axis=1)
  File "<stdin>", line 1
    df.apply(lambda x: x['b', 0] = 13, axis=1)
             ^
SyntaxError: expression cannot contain assignment, perhaps you meant "=="?
 

(Я понимаю, что есть лучшие способы для этого конкретного случая, но это всего лишь выдуманный пример.)

Как я могу установить значение по указанному индексу ряда?Я хотел бы иметь возможность просто использовать что-то вроде s.set_value(idx, 'my_val') и вернуть измененную (скопированную) серию.

Комментарии:

1. Не самый лучший, но apply занимает ряд, поэтому у вас есть name и index : df.apply(lambda x: np.where(x.index==0, 13, x) if x.name=='b' else x)

2. Круто, это долго для такой простой задачи, но это действительно работает.

Ответ №1:

Вы можете использовать pandas.Series.where() для возврата копии столбца с элементом по указанному индексу.

Это в основном похоже на использование .loc :

 >>> df['b'].where(df['b'].index != 1, 13)
0     0
1    13
2     0
Name: b, dtype: int64
 

Если у вас есть индекс, который не является a RangeIndex или который не начинается с нуля, вы можете вызвать reset_index() before where() , который будет похож на приведенный выше .loc , только имитируя поведение .iloc instead:

 >>> s = pd.Series({'a': 0, None: 0, True: 0})
>>> s
a       0
NaN     0
True    0
dtype: int64

>>> s.where(s.reset_index().index != 1, 13)
a        0
NaN     13
True     0
dtype: int64