let
и const
имеют две большие отличия от var
:
var
до его объявления имеет результат undefined
; доступ к let
или const
, прежде чем он будет объявлен бросками ReferenceError
:
console.log(aVar); // undefined
console.log(aLet); // causes ReferenceError: aLet is not defined
var aVar = 1;
let aLet = 2;
примеры, что let
объявления (и const
, которые работают одинаково) могут не быть подняты , так как aLet
не существует, пока ему не присвоено значение.
Это не так, однако let
и const
подняты (например, var
, class
и function
), но есть период между вводом области и объявлением там, где они не могут быть доступны. Этот период является временной мертвой зоной (TDZ).
TDZ заканчивается, когда aLet
объявлен объявлен , а не назначен :
//console.log(aLet) // would throw ReferenceError
let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10
Этот пример показывает, что let
поднят:
let x = 'outer value';
(function() {
// start TDZ for x
console.log(x);
let x = 'inner value'; // declaration ends TDZ for x
}());
Кредит: временная мертвая зона (TDZ) demystified
Доступ к x
во внутренней области все еще вызывает ReferenceError
. Если let
не были подняты, он будет записывать outer value
.
TDZ - это хорошо, потому что он помогает выделить ошибки - доступ к значению до того, как он был объявлен, редко преднамерен.
TDZ также применяется к аргументам функции по умолчанию. Аргументы оцениваются слева направо, и каждый аргумент находится в TDZ до тех пор, пока он не назначен:
// b is in TDZ until its value is assigned
function testDefaults(a=b, b) { }
testDefaults(undefined, 1); // throws ReferenceError because the evaluation of a reads b before it has been evaluated.
TDZ не включен по умолчанию в трансляторе babel.js . Включите режим «высокого соответствия», чтобы использовать его в REPL . Поставьте флаг es6.spec.blockScoping
, чтобы использовать его с CLI или в качестве библиотеки.
Рекомендуемое дополнительное чтение: TDZ demystified и ES6 Let, Const и «Temporal Dead» Зона "(TDZ) в глубину .
Вы можете использовать np.where . Если cond
является булевым массивом, а A
и B
являются массивами, тогда
C = np.where(cond, A, B)
определяет C равным A
, где cond
имеет значение True, а B
, где cond
- False.
import numpy as np
import pandas as pd
a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
df['que'] = np.where((df['one'] >= df['two']) & (df['one'] <= df['three'])
, df['one'], np.nan)
дает
one two three que
0 10 1.2 4.2 10
1 15 70 0.03 NaN
2 8 5 0 NaN
Если у вас более одного условия, вы можете использовать np.select . Например, если вы хотите df['que']
равняться df['two']
, когда df['one'] < df['two']
, то
conditions = [
(df['one'] >= df['two']) & (df['one'] <= df['three']),
df['one'] < df['two']]
choices = [df['one'], df['two']]
df['que'] = np.select(conditions, choices, default=np.nan)
дает
one two three que
0 10 1.2 4.2 10
1 15 70 0.03 70
2 8 5 0 NaN
Если мы можем предположить, что df['one'] >= df['two']
, когда df['one'] < df['two']
является False, тогда условия и варианты могут быть упрощены до
conditions = [
df['one'] < df['two'],
df['one'] <= df['three']]
choices = [df['two'], df['one']]
(Предположение может быть неверным, если df['one']
или df['two']
содержат NaNs.)
Обратите внимание, что
a = [['10', '1.2', '4.2'], ['15', '70', '0.03'], ['8', '5', '0']]
df = pd.DataFrame(a, columns=['one', 'two', 'three'])
определяет DataFrame со строковыми значениями. Поскольку они выглядят как числовые, вам может быть лучше преобразовать эти строки в float:
df2 = df.astype(float)
Это изменяет результаты, однако, поскольку строки сравниваются по каждому символу, а численные значения поплавков - численно.
In [61]: '10' <= '4.2'
Out[61]: True
In [62]: 10 <= 4.2
Out[62]: False
Вы можете использовать .equals
для столбцов или целых фреймов данных.
df['col1'].equals(df['col2'])
Если они равны, этот оператор вернет True
, else False
.
Одним из способов является использование булевой последовательности для индексации столбца df['one']
. Это дает вам новый столбец, в котором записи True
имеют то же значение, что и df['one']
, а значения False
равны NaN
.
Булевы серии заданы только вашим if
(хотя для &
необходимо использовать and
):
>>> df['que'] = df['one'][(df['one'] >= df['two']) & (df['one'] <= df['three'])]
>>> df
one two three que
0 10 1.2 4.2 10
1 15 70 0.03 NaN
2 8 5 0 NaN
Если вы хотите, чтобы значения NaN
были заменены другими значениями, вы можете использовать fillna
в новом столбце que
. Я использовал 0
вместо пустой строки здесь:
>>> df['que'] = df['que'].fillna(0)
>>> df
one two three que
0 10 1.2 4.2 10
1 15 70 0.03 0
2 8 5 0 0
Вы можете использовать apply () и сделать что-то вроде этого
df['que'] = df.apply(lambda x : x['one'] if x['one'] >= x['two'] and x['one'] <= x['three'] else "", axis=1)
или если вы предпочитаете не использовать лямбда
def que(x):
if x['one'] >= x['two'] and x['one'] <= x['three']:
return x['one']
else:
''
df['que'] = df.apply(que, axis=1)
Оберните каждое отдельное условие в круглых скобках, а затем используйте оператор &
для объединения условий:
df.loc[(df['one'] >= df['two']) & (df['one'] <= df['three']), 'que'] = df['one']
Вы можете заполнить несоответствующие строки, просто используя ~
(" не ") для инвертирования соответствия:
df.loc[~ ((df['one'] >= df['two']) & (df['one'] <= df['three'])), 'que'] = ''
Вам нужно использовать &
и ~
, а не and
и not
, поскольку работают операторы &
и ~
элемент за элементом.
Конечный результат:
df
Out[8]:
one two three que
0 10 1.2 4.2 10
1 15 70 0.03
2 8 5 0