在Pandas数据框中查找第一个匹配项

5

我需要使用一个DataFrame作为查找表,用于不是索引的列。例如(这只是一个简单的例子,仅用于说明):

import pandas as pd

westcoast = pd.DataFrame([['Washington','Olympia'],['Oregon','Salem'],
                          ['California','Sacramento']],
                        columns=['state','capital'])
print westcoast

        state     capital
0  Washington     Olympia
1      Oregon       Salem
2  California  Sacramento

查找并获取一个Series作为输出非常简单:

westcoast[westcoast.state=='Oregon'].capital

1    Salem
Name: capital, dtype: object

但我想获得字符串“Salem”:

westcoast[westcoast.state=='Oregon'].capital.values[0]

'Salem'

而且.values[0]看起来有些笨重...有更好的方法吗?

顺便说一句:我的真实数据最多可能有50行,但列数很多,所以如果我设置一个索引列,无论选择哪一列,都会有像这样的查找操作,它不是基于索引的,相对较少的行数意味着我不在乎它是否是O(n)查找。


1
你可以在这里查看答案 https://stackoverflow.com/questions/46352688/accessing-arrays-stored-in-pandas-dataframe#comment79665647_46352688 - BENY
2个回答

6

是的,如果查找总是从 Series 返回一个元素,您可以使用 Series.item

westcoast.loc[westcoast.state=='Oregon', 'capital'].item()

如果查找返回的结果为空或者有一个或多个值,但你只需要第一个值,可以通过异常处理来解决:

s = westcoast.loc[westcoast.state=='Oregon', 'capital']
s = np.nan if s.empty else s.iat[0] 
print (s) #Salem

s = westcoast.loc[westcoast.state=='New York', 'capital']
s = np.nan if s.empty else s.iat[0] 
print (s)
nan

更通用的解决方案是处理异常,因为有三种可能的输出场景:

westcoast = pd.DataFrame([['Washington','Olympia'],['Oregon','Salem'],
                          ['California','Sacramento'],['Oregon','Portland']],
                        columns=['state','capital'])

print (westcoast)
        state     capital
0  Washington     Olympia
1      Oregon       Salem
2  California  Sacramento
3      Oregon    Portland

s = westcoast.loc[westcoast.state=='Oregon', 'capital']

#if not value returned
if s.empty:
    s = 'no match'

#if only one value returned
elif len(s) == 1:
    s = s.item()
else:

# if multiple values returned, return a list of values
    s = s.tolist()

print (s)
['Salem', 'Portland']

可以创建一个查找函数:
def look_up(a):
    s = westcoast.loc[westcoast.state==a, 'capital']
    #for no match
    if s.empty:
        return np.nan
    #for match only one value
    elif len(s) == 1:
        return s.item()
    else:
    #for return multiple values
        return s.tolist()

print (look_up('Oregon'))
['Salem', 'Portland']

print (look_up('California'))
Sacramento

print (look_up('New Yourk'))
nan

哦,太棒了 - 出于某种原因,每当我浏览pandas文档时,总会发现我不知道的一些隐藏细节。谢谢!https://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.item.html#pandas.Series.item - Jason S
为什么要用 .loc?这样做更好吗? - Jason S
是的,如果数据量较大,loc更快。 - jezrael
2
嗯...似乎返回一个中间序列只是为了获取一个项(在索引重复的情况下)不好。难道没有更好的方法吗? - user48956

1
如果您要频繁进行这种查找,则最好将state作为索引。
state_capitals = westcoast.set_index('state')['capital']
print(state_capitals['Oregon'])
# Salem

使用索引,每次查找平均为O(1),而westcoast['state']=='Oregon'需要O(n)次比较。当然,构建索引也是O(n)的,因此您需要进行多次查找才能收回成本。
同时,一旦您拥有了state_capitals,语法就简单且类似于字典。这可能已经足够理由来构建state_capitals了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接