熊猫适用:多个条件和多个函数参数

时间:2019-04-22 22:57:53

标签: python-3.x pandas apply

简而言之,我试图将我的函数应用于选择行。我通过设置数据框子集,运行功能然后将子集合并回主数据框来使其工作。但是,这很麻烦,并且必须有一个更有效的解决方案使我无所适从。我发现了一些有用的帖子(hereherehere),它们有助于改进我的代码。

这是一个示例数据框:

data = {'firm': ['Smith', 'Jones', 'Smith New York', 'Jones International', 'Winter'], 
        'id': [np.nan, 732, 216, np.nan, 1714], 
        'url1': ['url', np.nan, 'url', 'url', 'url'],
        'url2': ['url', 'url', 'url', np.nan, 'url'],
        'text': ['foo', 'bar', np.nan, np.nan, 'foo bar']}
df = pd.DataFrame(data)

以下功能将解析网站,从而用户可以设置关键字以搜索已经下载的文件,并使用该存储的数据(如果存在)。如果上一次爬网发生了一段时间,则需要针对已更新的网站进行新的爬网。

def fetch(id, url, **kwargs):
    if backup == 'Yes':
        print('Fetching {} from {}'.format(id, url))
        # Actual fetching code
    else:
        print('Loading stored data for {}'.format(id))
        # Actual loading code 

该函数在我对单个URL进行测试时就可以使用,但是在尝试应用它时遇到了问题。我有多个条件才能运行它。目前,我使用它们来子集数据框。注意:如果存在两个网址,则首选url1。可以提交以下Pandas documentation个关键字参数。最初,我尝试了np.where。总共有4个条件,以下是两个:

df['content'] = np.where(df['text'].isna() & df['url1'].notnull() &
                            df['url2'].notnull() & df['firm'].str.contains('Smith'),
                         df['url1'].apply(fetch, args=df['id'], backup='Yes'),
                         np.where(df['text'].isna() & df['url1'].notnull() & 
                                    df['url2'].isna() & df['firm'].str.contains('Smith'),
                                  df['url1'].apply(**fetch, backup='Yes'**),
                                  pd.np.nan))
TypeError: fetch() takes 2 positional arguments but --some other number-- were given

因此,添加熊猫系列不起作用。而且我不知道如何将其添加为标量。 另一个失败的方法是只有两个列/系列:

df[['id', 'url1']][fd['text'].isna() & df['url1'].notnull() &
    df['url2'].notnull() & df['firm'].str.contains('Smith')].apply(fetch) # Should fetch nothing
df[['id', 'url1']][fd['text'].isna() & df['url1'].notnull() &
    df['url2'].isna() & df['firm'].str.contains('Smith')].apply(fetch) # Should fetch one
TypeError: ("fetch() missing 1 required positional argument: 'url1'", 'occurred at index id')

最后我尝试了lambda

df['text'].where(fd['text'].isna() & df['url1'].notnull() & df['url2'].isna()
   & df['fidm'].str.contains('Smith'), df[['id', 'url1']].apply(lambda x,y: get_XML(x,y)))
TypeError: ("<lambda>() missing 1 required positional argument: 'y'", 'occurred at index id')

我认为我缺少一些简单但显然很关键的东西。任何指针表示赞赏。


编辑-解决方案


我从Damien Ayers(请参见下文)中摘录了内容并简化了代码。然后,这也使我走上了解决之道:

def get_ft(text, xml, id, url1, url2, firm, backup= 'Yes'):
    if pd.notnull(id):
        if pd.isna(text) and pd.notnull(url1) and (pd.notnull(url2) or pd.isna(url2)):
            if 'Smith' in firm:
                return fetch(id, url1, backup)
            ... code continues

在这里,this discussion可以正确使用applylambda

df['text_new'] = df.apply(lambda x: x['text'], x['id'], x['url1'],
                                    x['url2'], x['firm'], backup), axis=1)

更清洁,更重要的是它可以工作。

0 个答案:

没有答案