Python Pandas: 通过搜索子字符串查找 table
Python Pandas: Lookup table by searching for substring
我有一个数据框,其中有一列用于应用程序用户代理。我需要做的是从此列中识别特定的应用程序。例如,
NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15 Darwin/14.0.0
将归入 Words With Friends
。
iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sudoku2; 143441-1,24 will be Sudoku by FingerArts etc.
我将有另一个数据框,其中包含我需要匹配的字符串。例如,
Keyword Game
NewWordsWithFriends Words With Friends
com.fingerarts.sudoku Sudoku by FingerArts
如何对 pandas 数据框进行这样的查找?例如数据框就像
user date user-agent
A 2015-09-02 13:45:56 NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15 Darwin/14.0.0
B 2015-08-31 23:04:21 iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sudoku2; 143441-1,24
我想要一个新列 GameName
查找后。
一种可能的实现方式是:
import pandas as pd
# some example data
qry = pd.DataFrame.from_dict({"Keyword": ["NewWordsWithFriends",
"com.fingerarts.sudoku"],
"Game": ["Words With Friends",
"Sudoku by FingerArts"]})
df = pd.DataFrame.from_dict({"user-agent" : ["NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15 Darwin/14.0.0",
"iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sudoku2; 143441-1,24"]})
keywords = qry.Keyword.tolist()
games = qry.Game.tolist()
def select(x):
for key, game in zip(keywords, games):
if key in x:
return game
df["GameName"] = df["user-agent"].apply(select)
这将给出:
In [41]: df
Out[41]:
user-agent GameName
0 NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15... Words With Friends
1 iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sud... Sudoku by FingerArts
如果您需要对大型数据集执行此操作,则需要测试此解决方案的性能,看看它是否足够快以达到您的目的。
如果不是,也许可以优化字符串的测试方式:
为所有可能的游戏设置一个外循环,然后使用 .apply
到 return 每个游戏每列的结果可以加快速度,因为它会避免在每次调用时循环遍历所有游戏select()
等
要确定瓶颈,您可以使用 line_profiler
(请参阅 How can I profile python code line-by-line?)。
df = pd.DataFrame({'date' : ['2015-09-02 13:45:56' , '2015-08-31 23:04:21'] , 'user-agent' : ['NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15 Darwin/14.0.0' , 'iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sudoku2; 143441-1,24'] })
map_df = pd.DataFrame({'Keyword' : ['NewWordsWithFriends' , 'com.fingerarts.sudoku'], 'Game' : [ 'Words With Friends', 'Sudoku by FingerArts'] })
mapping = {vals[1] : vals[0] for vals in map_df.values}
regex = '|'.join([keyword.replace('.' , '\.') for keyword in map_df['Keyword']])
def get_keyword(user_agent):
matches = re.findall(regex ,user_agent)
return matches[0] if len(matches) > 0 else np.nan
df['GameName'] = df['user-agent'].apply(get_keyword)
df['GameName'] = df['GameName'].map(mapping)
get_keyword
函数的另一个实现可能是
def get_keyword(user_agent):
for keyword in map_df['Keyword']:
if keyword in user_agent:
return keyword
另一种获取映射的方法是创建 series
mapping = pd.Series(map_df['Game'].values , index = map_df.Keyword )
我有一个数据框,其中有一列用于应用程序用户代理。我需要做的是从此列中识别特定的应用程序。例如,
NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15 Darwin/14.0.0
将归入 Words With Friends
。
iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sudoku2; 143441-1,24 will be Sudoku by FingerArts etc.
我将有另一个数据框,其中包含我需要匹配的字符串。例如,
Keyword Game
NewWordsWithFriends Words With Friends
com.fingerarts.sudoku Sudoku by FingerArts
如何对 pandas 数据框进行这样的查找?例如数据框就像
user date user-agent
A 2015-09-02 13:45:56 NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15 Darwin/14.0.0
B 2015-08-31 23:04:21 iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sudoku2; 143441-1,24
我想要一个新列 GameName
查找后。
一种可能的实现方式是:
import pandas as pd
# some example data
qry = pd.DataFrame.from_dict({"Keyword": ["NewWordsWithFriends",
"com.fingerarts.sudoku"],
"Game": ["Words With Friends",
"Sudoku by FingerArts"]})
df = pd.DataFrame.from_dict({"user-agent" : ["NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15 Darwin/14.0.0",
"iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sudoku2; 143441-1,24"]})
keywords = qry.Keyword.tolist()
games = qry.Game.tolist()
def select(x):
for key, game in zip(keywords, games):
if key in x:
return game
df["GameName"] = df["user-agent"].apply(select)
这将给出:
In [41]: df
Out[41]:
user-agent GameName
0 NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15... Words With Friends
1 iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sud... Sudoku by FingerArts
如果您需要对大型数据集执行此操作,则需要测试此解决方案的性能,看看它是否足够快以达到您的目的。
如果不是,也许可以优化字符串的测试方式:
为所有可能的游戏设置一个外循环,然后使用 .apply
到 return 每个游戏每列的结果可以加快速度,因为它会避免在每次调用时循环遍历所有游戏select()
等
要确定瓶颈,您可以使用 line_profiler
(请参阅 How can I profile python code line-by-line?)。
df = pd.DataFrame({'date' : ['2015-09-02 13:45:56' , '2015-08-31 23:04:21'] , 'user-agent' : ['NewWordsWithFriendsFree/2.3 CFNetwork/672.1.15 Darwin/14.0.0' , 'iPhone3,1; iPhone OS 7.1.2; com.fingerarts.sudoku2; 143441-1,24'] })
map_df = pd.DataFrame({'Keyword' : ['NewWordsWithFriends' , 'com.fingerarts.sudoku'], 'Game' : [ 'Words With Friends', 'Sudoku by FingerArts'] })
mapping = {vals[1] : vals[0] for vals in map_df.values}
regex = '|'.join([keyword.replace('.' , '\.') for keyword in map_df['Keyword']])
def get_keyword(user_agent):
matches = re.findall(regex ,user_agent)
return matches[0] if len(matches) > 0 else np.nan
df['GameName'] = df['user-agent'].apply(get_keyword)
df['GameName'] = df['GameName'].map(mapping)
get_keyword
函数的另一个实现可能是
def get_keyword(user_agent):
for keyword in map_df['Keyword']:
if keyword in user_agent:
return keyword
另一种获取映射的方法是创建 series
mapping = pd.Series(map_df['Game'].values , index = map_df.Keyword )