简而言之,我试图将我的函数应用于选择行。我通过设置数据框子集,运行功能然后将子集合并回主数据框来使其工作。但是,这很麻烦,并且必须有一个更有效的解决方案使我无所适从。我发现了一些有用的帖子(here,here和here),它们有助于改进我的代码。
这是一个示例数据框:
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可以正确使用apply
和lambda
:
df['text_new'] = df.apply(lambda x: x['text'], x['id'], x['url1'],
x['url2'], x['firm'], backup), axis=1)
更清洁,更重要的是它可以工作。