Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何将带有if语句的嵌套ItError转换为矢量化函数或其他更快的方法_Python_Python 3.x_Pandas_Dataframe - Fatal编程技术网

Python 如何将带有if语句的嵌套ItError转换为矢量化函数或其他更快的方法

Python 如何将带有if语句的嵌套ItError转换为矢量化函数或其他更快的方法,python,python-3.x,pandas,dataframe,Python,Python 3.x,Pandas,Dataframe,我知道pandas.DataFrame.iterrows非常慢,对于pandas/python中的简单函数,如“将每一列乘以另一列”,向量化很容易 我有一个稍微复杂一点的问题,我想不出一个方法来矢量化或映射这个问题。我正在对照主数据帧检查工作数据帧df1,以查看是否有任何条目是新的。这个问题有一些怪癖,每个名字可以有多个帐户,每个帐户可以有多个可能的名字 如果没有这些小怪癖,就很容易做海螺或类似的事情。不幸的是,数据集就是这样来的,没有办法提前知道哪个帐户将使用哪个昵称(而不需要在运行时花费同样

我知道pandas.DataFrame.iterrows非常慢,对于pandas/python中的简单函数,如“将每一列乘以另一列”,向量化很容易

我有一个稍微复杂一点的问题,我想不出一个方法来矢量化或映射这个问题。我正在对照主数据帧检查工作数据帧df1,以查看是否有任何条目是新的。这个问题有一些怪癖,每个名字可以有多个帐户,每个帐户可以有多个可能的名字

如果没有这些小怪癖,就很容易做海螺或类似的事情。不幸的是,数据集就是这样来的,没有办法提前知道哪个帐户将使用哪个昵称(而不需要在运行时花费同样多的处理能力)

我能想到的解决这个问题的最简单方法是使用嵌套的for/iterrow循环和if语句,如下面的示例所示。如果有人知道一种更快的方法,那就太好了,因为这种方法极其缓慢,以至于无法用于千行数据帧

import pandas as pd

df1 = pd.DataFrame({'names' : ['tim;timothy','tim', 'joseph', 'joe;joseph', 'bill', 'tim', 'bill', 'joe'],
                 'account' : ['w213', 'o993','x332', 'y313', 'z641', 'r323', 'p881', 'k445']})

df2 = pd.DataFrame({'names' : ['jill', 'joseph', 'tim', 'bill', 'timothy', 'bill', 'phil'],
                 'account' : ['y554', 'x332', 'w213', 'z641', 'w213', 'p881','k913']})


df1['new account'] = 1

for index_1, row_1 in df1.iterrows():
    possible_names = row_1['names'].split(';')

    for index_2, row_2 in df2.iterrows():
        if row_2['names'] in possible_names and row_1['account'] == row_2['account']:
            df1.loc[index_1, 'new account'] = 0

print(df1)
print(df2)

它不是最漂亮的,但一种方法是扩展并展平df1,然后与df2合并:

# flatten
df1_v2 = df1[["account"]].join(df1.names.str.split(";", expand=True))
df1_v2 = pd.melt(df1_v2.reset_index(),
                 ["index", "account"], value_name="names").dropna()

# merge
common = df1_v2.merge(df2)
df1["new account"] = 1
df1.loc[common["index"].values, "new account"] = 0
这让我

  account        names  new account
0    w213  tim;timothy            0
1    o993          tim            1
2    x332       joseph            0
3    y313   joe;joseph            1
4    z641         bill            0
5    r323          tim            1
6    p881         bill            0
7    k445          joe            1

这要经过中间层

In [145]: df1_v2.head()
Out[145]: 
   index account variable   names
0      0    w213        0     tim
1      1    o993        0     tim
2      2    x332        0  joseph
3      3    y313        0     joe
4      4    z641        0    bill
新答案 一起

d1 = df1.set_index('account').names.str.split(';').apply(set)
d2 = df2.groupby('account').names.apply(set).reindex(d1.index, fill_value=set())

new = (d1 - (d1 - d2)).astype(bool).__neg__().astype(np.uint8).rename('new')
df1.join(new, on='account')
解释
使用
设置
操作



-
运算符获取设置的差值。这样做两次,如果没有交叉点,我得到一个空集。空集的计算结果为
False
。但是没有交集意味着一个新帐户,所以我使用
\uuuu neg\uuuu
(否定,又称
~
)将
切换到

# find where there is no intersection
new = (d1 - (d1 - d2)).astype(bool).__neg__().astype(np.uint8).rename('new')
# join
df1.join(new, on='account')

  account        names  new
0    w213  tim;timothy    0
1    o993          tim    1
2    x332       joseph    0
3    y313   joe;joseph    1
4    z641         bill    0
5    r323          tim    1
6    p881         bill    0
7    k445          joe    1
旧答案 @DSM的答案要好得多
这更多的是一个解决方案的思想流

d2 = df2.assign(dummy=1).set_index(['account', 'names'])
split_df = df1.names.str.split(';', expand=True).rename(columns='name{}'.format)
d1 = df1.drop('names', 1).join(split_df)
d1 = d1.set_index('account').stack() \
       .reset_index('account', name='names') \
       .set_index(['account', 'names'])
df1.join(
    (~d1.join(d2).dummy.unstack().any(1)).astype(int).rename('new'),
    on='account')

  account        names  new
0    w213  tim;timothy    0
1    o993          tim    1
2    x332       joseph    0
3    y313   joe;joseph    1
4    z641         bill    0
5    r323          tim    1
6    p881         bill    0
7    k445          joe    1

[次要:请粘贴文本,而不是图像;外观上的细微改进不值得实际失去复制和粘贴的能力。]@root:我不仅看到了它们,还使用了这些定义来创建我的答案。但是能够复制和粘贴输出的用途仍然存在,特别是当(这里发生的)样本发生变化时。我已经更新了我的答案。检查这个:这太棒了!!!它提供相同的输出,并提供数量级的加速。我的大文件的运行时间从几个小时变为不到一秒。我已经更新了答案。我想你可能会喜欢这种方法。
d2

account
w213    {timothy, tim}
o993                {}
x332          {joseph}
y313                {}
z641            {bill}
r323                {}
p881            {bill}
k445                {}
Name: names, dtype: object
# find where there is no intersection
new = (d1 - (d1 - d2)).astype(bool).__neg__().astype(np.uint8).rename('new')
# join
df1.join(new, on='account')

  account        names  new
0    w213  tim;timothy    0
1    o993          tim    1
2    x332       joseph    0
3    y313   joe;joseph    1
4    z641         bill    0
5    r323          tim    1
6    p881         bill    0
7    k445          joe    1
d2 = df2.assign(dummy=1).set_index(['account', 'names'])
split_df = df1.names.str.split(';', expand=True).rename(columns='name{}'.format)
d1 = df1.drop('names', 1).join(split_df)
d1 = d1.set_index('account').stack() \
       .reset_index('account', name='names') \
       .set_index(['account', 'names'])
df1.join(
    (~d1.join(d2).dummy.unstack().any(1)).astype(int).rename('new'),
    on='account')

  account        names  new
0    w213  tim;timothy    0
1    o993          tim    1
2    x332       joseph    0
3    y313   joe;joseph    1
4    z641         bill    0
5    r323          tim    1
6    p881         bill    0
7    k445          joe    1