Python pandas数据帧上的numpy.where方法的结果是在完整数组上计算的还是在过滤数组上计算的?

Python pandas数据帧上的numpy.where方法的结果是在完整数组上计算的还是在过滤数组上计算的?,python,arrays,pandas,numpy,Python,Arrays,Pandas,Numpy,我想在pandas数据帧上使用numpyp.where来检查列中是否存在某个字符串。如果字符串存在,则应用拆分函数并获取第二个列表元素(如果不只是获取第一个字符)。但是,以下代码不起作用,它会抛出一个索引器:列表索引超出范围,因为第一个条目不包含下划线: import pandas as pd import numpy as np df = pd.DataFrame({'A':['a','a_1','b_','b_2_3']}) df["B"] = np.where(df.A.str.conta

我想在pandas数据帧上使用
numpyp.where
来检查列中是否存在某个字符串。如果字符串存在,则应用拆分函数并获取第二个列表元素(如果不只是获取第一个字符)。但是,以下代码不起作用,它会抛出一个
索引器:列表索引超出范围
,因为第一个条目不包含下划线:

import pandas as pd
import numpy as np
df = pd.DataFrame({'A':['a','a_1','b_','b_2_3']})
df["B"] = np.where(df.A.str.contains('_'),df.A.apply(lambda x: x.split('_')[1]),df.A.str[0])
仅调用
np。其中
返回条件为真的索引数组,因此我的印象是,
split
-命令将仅用于该数据子集:

np.where(df.A.str.contains('_'))
Out[14]: (array([1, 2, 3], dtype=int64),)
但是显然,
split
-命令用于整个未过滤数组,这对我来说似乎很奇怪,因为这可能是大量不必要的操作,会减慢计算速度

我不是在要求一个替代的解决方案,想出来并不难


我只是想知道这是预期结果还是pandas或numpy的问题。

在我看来
numpy。其中
仅按条件设置值,因此第二和第三个数组对所有数据进行计数-过滤和非过滤

如果需要,仅对过滤后的值应用某些函数:

mask = df.A.str.contains('_')
df.loc[mask, "B"] = df.loc[mask, "A"].str.split('_').str[1]
在您的解决方案中是错误,但问题与
np.where
无关。按
\uuu
拆分后,如果不存在值,则获取一个元素列表,因此按
[1]
选择列表的第二个值将引发错误:

print (df.A.apply(lambda x: x.split('_')))
0          [a]
1       [a, 1]
2        [b, ]
3    [b, 2, 3]
Name: A, dtype: object

print (df.A.apply(lambda x: x.split('_')[1]))
IndexError: list index out of range
因此,如果性能不重要,因为字符串函数的速度很慢,可以使用以下解决方案:

df["B"] = np.where(df.A.str.contains('_'), 
                   df.A.str.split('_').str[1],
                   df.A.str[0])

在我看来,
numpy。其中,
只按条件设置值,所以第二个和第三个数组对所有经过过滤和未过滤的数据进行计数

如果需要,仅对过滤后的值应用某些函数:

mask = df.A.str.contains('_')
df.loc[mask, "B"] = df.loc[mask, "A"].str.split('_').str[1]
在您的解决方案中是错误,但问题与
np.where
无关。按
\uuu
拆分后,如果不存在值,则获取一个元素列表,因此按
[1]
选择列表的第二个值将引发错误:

print (df.A.apply(lambda x: x.split('_')))
0          [a]
1       [a, 1]
2        [b, ]
3    [b, 2, 3]
Name: A, dtype: object

print (df.A.apply(lambda x: x.split('_')[1]))
IndexError: list index out of range
因此,如果性能不重要,因为字符串函数的速度很慢,可以使用以下解决方案:

df["B"] = np.where(df.A.str.contains('_'), 
                   df.A.str.split('_').str[1],
                   df.A.str[0])
Python不是一个简单的语言,因此代码会立即进行计算。生成器/迭代器确实引入了一些懒散,但这不适用于这里

如果我们拆分您的代码行,我们将得到以下语句:

  • df.A.str.contains(“"”)
  • df.A.apply(lambda x:x.split(“”“)[1])
  • df.A.str[0]
  • Python必须先对这些语句求值,然后才能将它们作为参数传递给
    np

    要看到所有这些情况的发生,我们可以将上述内容重写为显示一些输出的小函数:

    def fn_contains(x):
        print('contains', x)
        return '_' in x
    
    def fn_split(x):
        s = x.split('_')
        print('split', x, s)
        # check for errors here
        if len(s) > 1:
            return s[1]
    
    def fn_first(x):
        print('first', x)
        return x[0]
    
    然后,您可以使用以下工具在数据上运行它们:

    s = pd.Series(['a','a_1','b_','b_2_3'])
    np.where(
      s.apply(fn_contains),
      s.apply(fn_split),
      s.apply(fn_first)
    )
    
    你会看到一切都在有序地执行。这基本上就是在“内部”numpy/pandas中执行东西时发生的情况

    Python不是一个简单的程序,因此代码会立即被评估。生成器/迭代器确实引入了一些懒散,但这不适用于这里

    如果我们拆分您的代码行,我们将得到以下语句:

  • df.A.str.contains(“"”)
  • df.A.apply(lambda x:x.split(“”“)[1])
  • df.A.str[0]
  • Python必须先对这些语句求值,然后才能将它们作为参数传递给
    np

    要看到所有这些情况的发生,我们可以将上述内容重写为显示一些输出的小函数:

    def fn_contains(x):
        print('contains', x)
        return '_' in x
    
    def fn_split(x):
        s = x.split('_')
        print('split', x, s)
        # check for errors here
        if len(s) > 1:
            return s[1]
    
    def fn_first(x):
        print('first', x)
        return x[0]
    
    然后,您可以使用以下工具在数据上运行它们:

    s = pd.Series(['a','a_1','b_','b_2_3'])
    np.where(
      s.apply(fn_contains),
      s.apply(fn_split),
      s.apply(fn_first)
    )
    

    你会看到一切都在有序地执行。这基本上就是numpy/pandas内部执行东西时发生的情况

    我很惊讶
    df.A.str.split(“''').str[1]
    可以工作,我不会想到在列表中使用
    .str
    -访问器。我确实提出了这个解决方案:
    df.A.apply(lambda x:x.split(“'u'[1]如果“'u”在x else x[0])
    。我很惊讶
    df.A.str.split(''u'.str[1]
    有效,不会想到在列表上使用
    .str
    -accessor。我确实提出了这个解决方案:
    df.A.apply(lambda x:x.split(“')[1]if“”in x else x[0])
    。因此它首先计算所有三个内部语句,然后再进入封闭的
    np.where
    。如果没有
    np,则不知道如何使用第一条语句作为第二条和第三条语句的过滤器。我理解得对吗?听起来不错,已经用一个演示进行了更新,这样你就有希望看到发生了什么。因此,在进入封闭的
    np.where
    之前,它首先计算所有三个内部语句。如果没有
    np,则不知道如何使用第一条语句作为第二条和第三条语句的过滤器。我理解的对吗?听起来不错,已经更新了一个演示,希望你能看到发生了什么