私信  •  关注

cs95

cs95 最近创建的主题
cs95 最近回复了
6 年前
回复了 cs95 创建的主题 » 在python中,与(and,&,or,|)等价的是什么?

太长,读不下去了 熊猫中的逻辑运算符是 & , | ~ ,和括号 (...) 这很重要!

蟒蛇的 and , or not 逻辑运算符设计用于处理标量。所以Pandas必须做得更好,重写位运算符以实现 矢量化 此功能的(元素)版本。

下面是python中的( exp1 exp2 是计算为布尔结果的表达式)。。。

exp1 and exp2              # Logical AND
exp1 or exp2               # Logical OR
not exp1                   # Logical NOT

...将转化为。。。

exp1 & exp2                # Element-wise logical AND
exp1 | exp2                # Element-wise logical OR
~exp1                      # Element-wise logical NOT

为了熊猫。

如果在执行逻辑运算的过程中 ValueError ,则需要使用括号进行分组:

(exp1) op (exp2)

例如

(df['col1'] == x) & (df['col2'] == y) 

等等


Boolean Indexing :常见的操作是通过逻辑条件计算布尔掩码以过滤数据。熊猫提供 操作员: & 对于逻辑和逻辑, | 用于逻辑OR,以及 ~ 当然不是。

考虑以下设置:

np.random.seed(0)
df = pd.DataFrame(np.random.choice(10, (5, 3)), columns=list('ABC'))
df

   A  B  C
0  5  0  3
1  3  7  9
2  3  5  2
3  4  7  6
4  8  8  1

逻辑与

对于 df 上面,假设您希望返回A<5和B>5.这是通过分别计算每个条件的掩码,并对它们进行求和来实现的。

按位重载 & 操作人员
在继续之前,请注意这些文件的特别摘录,其中

另一种常见的操作是使用布尔向量来过滤 数据运营商包括: | 对于 , & 对于 ~ 对于 . 这些 ,因为默认情况下Python将 计算表达式,例如 df.A > 2 & df.B < 3 df.A > (2 & df.B) < 3 ,而所需的评估顺序为 (df.A > 2) & (df.B < 3) .

因此,考虑到这一点,元素逻辑AND可以通过位运算符实现 & :

df['A'] < 5

0    False
1     True
2     True
3     True
4    False
Name: A, dtype: bool

df['B'] > 5

0    False
1     True
2    False
3     True
4     True
Name: B, dtype: bool

(df['A'] < 5) & (df['B'] > 5)

0    False
1     True
2    False
3     True
4    False
dtype: bool

接下来的过滤步骤很简单,

df[(df['A'] < 5) & (df['B'] > 5)]

   A  B  C
1  3  7  9
3  4  7  6

括号用于覆盖按位运算符的默认优先顺序,按位运算符的优先级高于条件运算符 < > .参见 Operator Precedence 在python文档中。

如果不使用括号,则表达式的计算结果不正确。例如,如果您不小心尝试了以下操作:

df['A'] < 5 & df['B'] > 5

它被解析为

df['A'] < (5 & df['B']) > 5

这就变成了,

df['A'] < something_you_dont_want > 5

这就变成了(参见上的python文档) chained operator comparison ),

(df['A'] < something_you_dont_want) and (something_you_dont_want > 5)

这就变成了,

# Both operands are Series...
something_else_you_dont_want1 and something_else_you_dont_want2

哪个扔

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

所以,不要犯那个错误! 1.

避免括号分组
解决方法其实很简单。对于数据帧,大多数操作符都有相应的绑定方法。如果单个掩码是使用函数而不是条件运算符构建的,则不再需要按参数分组来指定求值顺序:

df['A'].lt(5)

0     True
1     True
2     True
3     True
4    False
Name: A, dtype: bool

df['B'].gt(5)

0    False
1     True
2    False
3     True
4     True
Name: B, dtype: bool

df['A'].lt(5) & df['B'].gt(5)

0    False
1     True
2    False
3     True
4    False
dtype: bool

请参阅 Flexible Comparisons. .总结一下,我们有

╒════╤════════════╤════════════╕
│    │ Operator   │ Function   │
╞════╪════════════╪════════════╡
│  0 │ >          │ gt         │
├────┼────────────┼────────────┤
│  1 │ >=         │ ge         │
├────┼────────────┼────────────┤
│  2 │ <          │ lt         │
├────┼────────────┼────────────┤
│  3 │ <=         │ le         │
├────┼────────────┼────────────┤
│  4 │ ==         │ eq         │
├────┼────────────┼────────────┤
│  5 │ !=         │ ne         │
╘════╧════════════╧════════════╛

避免使用括号的另一个选项是使用 DataFrame.query (或 eval ):

df.query('A < 5 and B > 5')

   A  B  C
1  3  7  9
3  4  7  6

我有 广泛地 记录在案 query 评估 在里面 Dynamic Expression Evaluation in pandas using pd.eval() .

operator.and_
允许您以功能性方式执行此操作。内部通话 Series.__and__ 它对应于按位运算符。

import operator 

operator.and_(df['A'] < 5, df['B'] > 5)
# Same as,
# (df['A'] < 5).__and__(df['B'] > 5) 

0    False
1     True
2    False
3     True
4    False
dtype: bool

df[operator.and_(df['A'] < 5, df['B'] > 5)]

   A  B  C
1  3  7  9
3  4  7  6

你通常不需要这个,但知道它很有用。

概括起来: np.logical_and (及 logical_and.reduce )
另一种选择是使用 NP逻辑_和 ,也不需要括号:

np.logical_and(df['A'] < 5, df['B'] > 5)

0    False
1     True
2    False
3     True
4    False
Name: A, dtype: bool

df[np.logical_and(df['A'] < 5, df['B'] > 5)]

   A  B  C
1  3  7  9
3  4  7  6

NP逻辑_和 是一个 ufunc (Universal Functions) ,而且大多数UFUNC都有 reduce 方法这意味着更容易概括 logical_and 如果你有多个口罩和。比如说,戴口罩和口罩 m1 m2 m3 具有 & ,你必须这么做

m1 & m2 & m3

然而,一个更简单的选择是

np.logical_and.reduce([m1, m2, m3])

这是非常强大的,因为它可以让你在上面构建更复杂的逻辑(例如,在列表中动态生成掩码并添加所有掩码):

import operator

cols = ['A', 'B']
ops = [np.less, np.greater]
values = [5, 5]

m = np.logical_and.reduce([op(df[c], v) for op, c, v in zip(ops, cols, values)])
m 
# array([False,  True, False,  True, False])

df[m]
   A  B  C
1  3  7  9
3  4  7  6

1-我知道我在反复强调这一点,但请容忍我。这是一个 非常 , 非常 初学者常见的错误,必须解释得非常透彻。


逻辑或

对于 df 上面,假设您希望返回A==3或B==7的所有行。

按位重载 |

df['A'] == 3

0    False
1     True
2     True
3    False
4    False
Name: A, dtype: bool

df['B'] == 7

0    False
1     True
2    False
3     True
4    False
Name: B, dtype: bool

(df['A'] == 3) | (df['B'] == 7)

0    False
1     True
2     True
3     True
4    False
dtype: bool

df[(df['A'] == 3) | (df['B'] == 7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

如果还没有,请阅读 逻辑与

或者,也可以使用

df[df['A'].eq(3) | df['B'].eq(7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

operator.or_
电话 Series.__or__ 在引擎盖下面。

operator.or_(df['A'] == 3, df['B'] == 7)
# Same as,
# (df['A'] == 3).__or__(df['B'] == 7)

0    False
1     True
2     True
3     True
4    False
dtype: bool

df[operator.or_(df['A'] == 3, df['B'] == 7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

np.logical_or
对于两种情况,使用 logical_or :

np.logical_or(df['A'] == 3, df['B'] == 7)

0    False
1     True
2     True
3     True
4    False
Name: A, dtype: bool

df[np.logical_or(df['A'] == 3, df['B'] == 7)]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

对于多个遮罩,请使用 logical_or.reduce :

np.logical_or.reduce([df['A'] == 3, df['B'] == 7])
# array([False,  True,  True,  True, False])

df[np.logical_or.reduce([df['A'] == 3, df['B'] == 7])]

   A  B  C
1  3  7  9
2  3  5  2
3  4  7  6

不符合逻辑

戴上口罩,比如

mask = pd.Series([True, True, False])

如果需要反转每个布尔值(以便最终结果为 [False, False, True] ),则可以使用以下任何方法。

按位 ~

~mask

0    False
1    False
2     True
dtype: bool

同样,表达式需要加括号。

~(df['A'] == 3)

0     True
1    False
2    False
3     True
4     True
Name: A, dtype: bool

这在内部称为

mask.__invert__()

0    False
1    False
2     True
dtype: bool

但不要直接使用它。

operator.inv
内部通话 __invert__ 在这个系列中。

operator.inv(mask)

0    False
1    False
2     True
dtype: bool

np.logical_not
这是numpy的变种。

np.logical_not(mask)

0    False
1    False
2     True
dtype: bool

笔记 NP逻辑_和 可以替代 np.bitwise_and , 逻辑的 具有 bitwise_or logical_not 具有 invert .

6 年前
回复了 cs95 创建的主题 » Python从嵌套字典中获取给定键的值

假设(希望是合理的)您试图找到的值不是包含双引号的字符串( " )在它们中,可以使用regex在JSONified字典中搜索键,并返回相应的值。

import re
import json

def get_value(d, key):
    try:
        # for python-2.x, use,
        # return re.search(r'"{k}": "(.*?)"'.format(key), json.dumps(d)).group(1)
        return re.search(f'"{key}": "(.*?)"', json.dumps(d)).group(1)
    except AttributeError:  # no match
        return np.nan 

get_value(fruit_details, 'statusCode')
# 'S-1'

这是一个普遍的问题。在这种情况下,为 package ,以便您可以安全地参考 包裹 bar 通过 包裹 命名空间,而不会遇到命名冲突。

import package
from package import bar

def foo(bar=42):
    do_something_with_bar(package.bar(bar))

您仍然会导入模块一次,但是现在有两种方法可以引用 酒吧 是的。

6 年前
回复了 cs95 创建的主题 » python round不返回整数

apply 调用 round 在每个列上连续运行。数据框列是 Series 对象,以及 these have a __round__ dunder method defined on them 行为稍有不同。实际上这就是 打电话给 系列 .

round(a[0])

0    1.0
1    1.0
Name: 0, dtype: float64

# Same as,
a[0].__round__()

0    1.0
1    1.0
Name: 0, dtype: float64

与python的典型行为相比 标量:

round(1.5)
# 2

 # Same as,
(1.5).__round__()
# 2

如果你想要同样的行为,使用 applymap .

a.applymap(round)

   0  1
0  1  3
1  1  5

适用于 在每一个 要素 (标量),舍入为整数。

或者,我推荐的解决方案,

a.round().astype(int)

   0  1
0  1  3
1  1  5

请注意,这不会对包含丢失数据(nan)的列进行类型转换。

6 年前
回复了 cs95 创建的主题 » 与python列表一起使用的and运算符[重复]

DR

我们首先总结两个逻辑运算符的两种行为 and or . 这些习语将构成我们下面讨论的基础。

返回第一个错误值(如果有),否则返回最后一个 表达式中的值。

返回第一个truthy值(如果有),否则返回最后一个 表达式中的值。

这些行为也总结在 the docs ,尤其是在这个表中:

enter image description here

返回布尔值的唯一运算符是 not 操作员。


“真实”和“真实”评价

声明

len(args) and max(args) - min(args)

是一个 非常 小精灵 简洁(而且不太可读)的表达方式 args 不为空,返回结果 max(args) - min(args) “,否则返回 0 . 一般来说,它是 if-else 表达式。例如,

exp1 and exp2

应该(大致)翻译成:

r1 = exp1
if not r1:
    r1 = exp2

或者,同等地,

r1 = exp1 if exp1 else exp2

在哪里? exp1 exp2 是任意的python对象,或返回某个对象的表达式。理解逻辑用法的关键 这里的运算符理解它们不限于对布尔值进行操作或返回布尔值。任何具有真实性值的对象都可以在这里进行测试。这包括 int , str , list , dict , tuple , set , NoneType ,以及用户定义的对象。短路规则仍然适用。

但什么是真实?
它指的是在条件表达式中使用对象时如何计算对象。@帕特里克·豪在书中很好地总结了真理。 this post .

所有的价值观都被认为是“真理”,除了以下的 “法西斯”:

  • None
  • False
  • 0.0
  • 0j
  • Decimal(0)
  • Fraction(0, 1)
  • [] 空的 列表
  • {} 空的 双关语
  • () 空的 元组
  • '' 空的 STR
  • b'' 空的 bytes
  • set() 空的 设置
  • 空的 range ,像 range(0)
  • 对象
    • obj.__bool__() 收益率
    • obj.__len__() 收益率

“truthy”值将满足 if while 声明。我们用“truthy”和“falsy”来区别 bool 价值观 True .


怎么 作品

我们以op的问题为基础,讨论了在这些情况下这些运算符是如何实现的。

给出一个函数的定义

def foo(*args):
    ...

如何返回最小值和最大值之间的差异 在一个包含零个或多个参数的列表中?

找到最小值和最大值很容易(使用内置函数!)。这里唯一的障碍是适当地处理参数列表可能为空的角点情况(例如,调用 foo() )我们可以做到这两个在一条线上感谢 操作员:

def foo(*args):
     return len(args) and max(args) - min(args)

foo(1, 2, 3, 4, 5)
# 4

foo()
# 0

自从 如果第一个表达式是 . 注意,如果第一个表达式的计算结果为truthy,则返回值为 总是 结果是 第二个表达式 . 如果第一个表达式的计算结果为false,则返回的结果是第一个表达式的结果。

在上面的函数中,如果 foo 接收一个或多个参数, len(args) 大于 (正数),因此返回的结果是 最大(args)-最小(args) . 哦,如果没有参数被传递, 伦琴(ARGS) 那是假的,而且 返回。

请注意,编写此函数的另一种方法是:

def foo(*args):
    if not len(args):
        return 0

    return max(args) - min(args)

或者,更简洁地说,

def foo(*args):
    return 0 if not args else max(args) - min(args)

当然,这些函数都不执行任何类型检查,所以除非您完全信任所提供的输入, 依赖于这些构造的简单性。


怎么 作品

我解释的工作 以类似的方式,举一个人为的例子。

给出一个函数的定义

def foo(*参数):
…

你将如何完成 返回所有数字 9000 ?

我们使用 来处理这个角落的案子。我们定义 AS:

def foo(*args):
     return [x for x in args if x > 9000] or 'No number over 9000!'

foo(9004, 1, 2, 500)
# [9004]

foo(1, 2, 3, 4)
# 'No number over 9000!'

对列表执行筛选以保留所有数字 九千 . 如果存在任何这样的数字,则列表理解的结果是一个非空列表,这是正确的,因此将返回该列表(此处短路)。如果没有这样的数字,那么列表comp的结果是 [] 这是假的。所以第二个表达式现在被求值(非空字符串)并返回。

使用条件句,我们可以重新编写这个函数,

def foo(*args):
    r = [x for x in args if x > 9000]
    if not r:
        return 'No number over 9000!' 

    return r

和以前一样,这个结构在错误处理方面更加灵活。

6 年前
回复了 cs95 创建的主题 » python数据帧中的部分转换列

为什么不将列保留为字符串?如果您希望“1234”和“0001234”被同等对待,则始终可以去掉前导零。

df.Product_ID.astype(str).str.lstrip('0')

0    ABCD
1    1234
2    1234
3    2345
4    4567
5    EFGH
Name: Product_ID, dtype: object
6 年前
回复了 cs95 创建的主题 » 使用python在3d数组中裁剪3d数组的最快方法

Numpy非常容易支持这样的切片:

dim = 5
x = dim // 2
i,j,k = ind

volume_3d = arr[i-x:i+(dim-x), j-x:j+(dim-x), k-x:k+(dim-x)].copy()

# Your implementation.
dim = 5
x = dim // 2
arr = np.random.randn(7, 7, 7)
el = ind[0]
group = arr[el-x:el+(dim-x)] 
volume_3d = []
for i in group:
    volume_2d = i[ind[1]-x:ind[1]+(dim-x), ind[2]-x:ind[2]+(dim-x)]
    volume_3d.append (volume_2d)

# Proposed in this post.
i,j,k = ind
volume_3d_2 = arr[i-x:i+(dim-x), j-x:j+(dim-x), k-x:k+(dim-x)]

print(np.array_equal(volume_3d, volume_3d_2))
True
8 年前
回复了 cs95 创建的主题 » python自上而下迭代[重复]

x绑定整数对象5。

对, x 是一个变量,包含对整数对象5的引用,该对象 y 也包含对的引用。

返回语句在这里实际返回什么?int对象5? 或者变量名y?或者绑定到对象5?或者别的什么?

准确地说,是 参考 返回到整数对象5。举个例子,看看这个:

In [1]: def foo():
   ...:     y = 5
   ...:     print(id(y))
   ...:     return y
   ...: 

In [2]: x = foo()
4297370816

In [3]: id(x)
Out[3]: 4297370816

如何获取return语句返回的值?

通过访问 参考 return 传回呼叫者。

6 年前
回复了 cs95 创建的主题 » 迭代python字典[重复]

如果您需要单独存储密钥,这里有一个解决方案,它比迄今为止提供的所有其他解决方案都需要更少的输入,使用 Extended Iterable Unpacking (python3.x+)。

newdict = {1: 0, 2: 0, 3: 0}
*k, = newdict

k
# [1, 2, 3]

            ╒═══════════════╤═════════════════════════════════════════╕
            │ k = list(d)   │   9 characters (excluding whitespace)   │
            ├───────────────┼─────────────────────────────────────────┤
            │ k = [*d]      │   6 characters                          │
            ├───────────────┼─────────────────────────────────────────┤
            │ *k, = d       │   5 characters                          │
            ╘═══════════════╧═════════════════════════════════════════╛
6 年前
回复了 cs95 创建的主题 » 迭代python字典[重复]

您也可以使用 列表理解 :

>>> newdict = {1:0, 2:0, 3:0}
>>> [k  for  k in  newdict.keys()]
[1, 2, 3]

或者,更短,

>>> [k  for  k in  newdict]
[1, 2, 3]

注:3.7下的版本不保证订购(订购仍然只是CPython 3.6的一个实现细节)。

6 年前
回复了 cs95 创建的主题 » python中的replace函数给出了错误的结果

replace regex=True

df['Final'] = df['AlmostFinal'].replace(
    [r'KOPL', r'RWP.*?(?=A|B)', r'MM.*(?=A|B)'], 'KOLPOL', regex=True)
df

   Sample AlmostFinal       Final
0       1    KOPLA234  KOLPOLA234
1       1    KOPLA234  KOLPOLA234
2       2    RWPLB253  KOLPOLB253
3       3    MMPLA415  KOLPOLA415
4       3    MMPLA415  KOLPOLA415


pat = ['KOPL', 'RWP', 'MM']
df['Final'] = df['AlmostFinal'].replace(
    [rf'{p}.*(?=A|B)' for p in pat], 'KOLPOL', regex=True)  # need python3.6+
df

   Sample AlmostFinal       Final
0       1    KOPLA234  KOLPOLA234
1       1    KOPLA234  KOLPOLA234
2       2    RWPLB253  KOLPOLB253
3       3    MMPLA415  KOLPOLA415
4       3    MMPLA415  KOLPOLA415

pat = ['KOPL', 'RWPL', 'MMPL']
df['AlmostFinal'].replace(pat, 'KOLPOL', regex=True)

0    KOLPOLA234
1    KOLPOLA234
2    KOLPOLB253
3    KOLPOLA415
4    KOLPOLA415
Name: AlmostFinal, dtype: object