#python #pandas #dataframe
#python #pandas #фрейм данных
Вопрос:
Я знаю, что assign может помочь создать / изменить один столбец на основе лямбда-функции следующим образом:
df.assign(c = lambda x: x.sum())
Но я не смог найти способ сделать это с помощью if-statement, если я хочу сделать оператор встроенным, а не выполнять его отдельно вне операции.
Возможно ли реализовать это, не делая ничего другого за пределами операции:
df.assign(c = lambda x: x.num_col.sum() if x.num_col > 0)
Приведенная выше команда возвращает «SyntaxError: недопустимый синтаксис»
Ответ №1:
IIUC вы можете сделать это таким образом:
Данные:
In [6]: df = pd.DataFrame(np.random.randn(10,2),columns=list('ab'))
In [7]: df
Out[7]:
a b
0 0.493970 1.095644
1 0.128510 -0.542144
2 0.136247 -0.544499
3 -0.540835 -0.100574
4 0.052725 -0.164856
5 -1.201619 1.578153
6 1.921872 0.505875
7 -2.519725 0.282050
8 -1.581868 -0.240352
9 -0.071207 -1.366953
In [8]: df.iloc[:6]
Out[8]:
a b
0 0.493970 1.095644
1 0.128510 -0.542144
2 0.136247 -0.544499
3 -0.540835 -0.100574
4 0.052725 -0.164856
5 -1.201619 1.578153
6 1.921872 0.505875
давайте найдем сумму положительных значений в a
столбце для индексов: [0:6]
:
In [9]: df.iloc[:6].query('a > 0').a.sum()
Out[9]: 2.733322288547374
Решение:
In [10]: df.iloc[:6].assign(c=lambda x: x.query('a > 0').a.sum())
Out[10]:
a b c
0 0.493970 1.095644 2.733322
1 0.128510 -0.542144 2.733322
2 0.136247 -0.544499 2.733322
3 -0.540835 -0.100574 2.733322
4 0.052725 -0.164856 2.733322
5 -1.201619 1.578153 2.733322
6 1.921872 0.505875 2.733322
то же самое с переименованными столбцами:
In [11]: df.iloc[:6].rename(columns={'a':'AAA', 'b':'BBB'}).assign(c=lambda x: x.query('AAA > 0').AAA.sum())
Out[11]:
AAA BBB c
0 0.493970 1.095644 2.733322
1 0.128510 -0.542144 2.733322
2 0.136247 -0.544499 2.733322
3 -0.540835 -0.100574 2.733322
4 0.052725 -0.164856 2.733322
5 -1.201619 1.578153 2.733322
6 1.921872 0.505875 2.733322
ОБНОВЛЕНИЕ: начиная с Pandas 0.20.1, индексатор .ix устарел в пользу более строгого .индексаторы iloc и .loc.
Комментарии:
1. Спасибо, но df уже будет задействован в ряде операций, и для этого придется все еще разделять операцию.
2. @JingtaoYun, я не понял — что ты имеешь в виду? Вам нужен новый виртуальный столбец (с использованием
assign
метода) или постоянный ?3. виртуальный, потому что я хочу выполнить множество операций за df, прежде чем выполнять assign, таких как df.ix[].rename()…assign() .. Таким образом, df не является исходным df для применения функции назначения.
4. Это отлично работает. Извините, что не сделал это более понятным в начале. Спасибо @MaxU
Ответ №2:
Синтаксис недопустим, потому что вы используете троичное условие, но только первую половину.
Троичное условие позволяет вам написать if
оператор, подобный этому:
a = 1 if b > 0 else 0
В вашем случае вы могли бы написать что-то вроде:
df = (
df
.assign(c = lambda x: x.num_col.sum() if x.num_col > 0 else 0)
)
Обратите внимание на добавление else 0
в конце.
Комментарии:
1. Вы пытались запустить этот код? Я не думаю, что это действительно сработает.
2. Спасибо Майклу за то, что поделился этим знанием. Но это не работает с ошибкой: ValueError: значение истинности ряда неоднозначно. Используйте .empty , .bool(),.item(),.any() или.all() .