2017-04-22 69 views
0

我有兩個dataframes A和B. A是具有500線較小和B是具有20000行大。 A的欄目有:在一個數據幀匹配多個字符串從行到行中另一

A.columns = ['name','company','model','family'] 

和B的列有:

B.columns = ["title", "price"] 

B中的標題欄是一個大混亂的字符串,但它確實包含在一個即公司,模型和家人從3列字符串(忘記'名字'專欄,因爲A本身的名字是公司,模特和家庭的組合)。 我需要從每一行匹配的單排在B,這是我的解決方案:

out=pd.DataFrame(columns={0,1,2,3,4,5}) 
out.columns=["name", 'company', 'model', 'family', 'title', 'price'] 

for index, row in A.iterrows(): 
    lst=[A.loc[index,'family'], A.loc[index,'model'], A.loc[index,'company']] 
    for i, r in B.iterrows(): 
     if all(w in B.loc[i,'title'] for w in lst):   
      out.loc[index,'name']=A.loc[index,'name'] 
      out.loc[index,'company']=A.loc[index,'company'] 
      out.loc[index,'model']=A.loc[index,'model'] 
      out.loc[index,'family']=A.loc[index,'family'] 

      out.loc[index,'title']=B.loc[i,'title'] 
      out.loc[index,'price']=B.loc[i,'price'] 
      break 

這做這項工作的效率非常低,並需要很長的時間。我知道這是一個「記錄鏈接」的問題,人們正在研究它的精度和速度,但有沒有在熊貓這樣一個更快更有效的方式?如果我檢查的稱號從LST只有一兩個項目,這將是快,但我擔心的是,它會降低精度...

在準確性方面,我寧願得到比錯誤的比賽少的比賽。

此外,A.dtypes和B.dtypes表明,這兩種dataframes'列對象:

title   object 
price   object 
dtype: object 

我明白任何評論。 A B

我: 感謝

********* UPDATE ***********

部分中的兩個文件,可以發現做一些清潔他們作爲:

import pandas as pd 
import numpy as np 
from scipy import stats 
import matplotlib.colors as mcol 
import matplotlib.cm as cm 
import matplotlib.pyplot as plt 
import math 

A = pd.read_csv('A.txt', delimiter=',', header=None) 
A.columns = ['product name','manufacturer','model','family','announced date'] 

for index, row in A.iterrows():  
    A.loc[index, "product name"] = A.loc[index, "product name"].split('"')[3] 
    A.loc[index, "manufacturer"] = A.loc[index, "manufacturer"].split('"')[1] 
    A.loc[index, "model"] = A.loc[index, "model"].split('"')[1] 
    if 'family' in A.loc[index, "family"]: 
     A.loc[index, "family"] = A.loc[index, "family"].split('"')[1] 
    if 'announced' in A.loc[index, "family"]: 
     A.loc[index, "announced date"] = A.loc[index, "family"] 
     A.loc[index, "family"] = '' 
    A.loc[index, "announced date"] = A.loc[index, "announced date"].split('"')[1] 

A.columns=['product name','manufacturer','model','family','announced date'] 
A.reset_index() 

B = pd.read_csv('B.txt', error_bad_lines=False, warn_bad_lines=False, header=None) 

B.columns = ["title", "manufacturer", "currency", "price"] 
pd.options.display.max_colwidth=200 

for index, row in B.iterrows(): 
    B.loc[index,'manufacturer']=B.loc[index,'manufacturer'].split('"')[1] 
    B.loc[index,'currency']=B.loc[index,'currency'].split('"')[1] 
    B.loc[index,'price']=B.loc[index,'price'].split('"')[1] 
    B.loc[index,'title']=B.loc[index,'title'].split('"')[3] 

則Andrew的方法,因爲在回答提示:

def match_strs(row): 
    return np.where(B.title.str.contains(row['manufacturer']) & \ 
        B.title.str.contains(row['family']) & \ 
        B.title.str.contains(row['model']))[0][0] 

A['merge_idx'] = A.apply(match_strs, axis='columns') 

(A.merge(B, left_on='merge_idx', right_on='index', right_index=True, how='right') 
    .drop('merge_idx', 1) 
    .dropna()) 

就像我說的,一定的併發症發生,我想不通。您的幫助

回答

1

這裏非常感謝的一些樣本數據一起工作:

import numpy as np 
import pandas as pd 

# make A df 
manufacturer = ['A','B','C'] 
model = ['foo','bar','baz'] 
family = ['X','Y','Z'] 
name = ['{}_{}_{}'.format(manufacturer[i],model[i],family[i]) for i in range(len(company))] 
A = pd.DataFrame({'name':name,'manufacturer': manufacturer,'model':model,'family':family}) 

# A 
    manufacturer family model  name 
    0  A  X foo A_foo_X 
    1  B  Y bar B_bar_Y 
    2  C  Z baz C_baz_Z 

# make B df 
title = ['blahblahblah'] 
title.extend(['{}_{}'.format(n, 'blahblahblah') for n in name]) 
B = pd.DataFrame({'title':title,'price':np.random.randint(1,100,4)}) 

# B 
    price     title 
0  62   blahblahblah 
1  7 A_foo_X_blahblahblah 
2  92 B_bar_Y_blahblahblah 
3  24 C_baz_Z_blahblahblah 

我們可以在AB,根據您的匹配條件匹配的行索引的功能,並將其存儲在一個新的列:

def match_strs(row): 
    match_result = (np.where(B.title.str.contains(row['manufacturer']) & \ 
          B.title.str.contains(row['family']) & \ 
          B.title.str.contains(row['model']))) 
    if not len(match_result[0]): 
     return None 
    return match_result[0][0] 

A['merge_idx'] = A.apply(match_strs, axis='columns') 

然後合併AB

(A.merge(B, left_on='merge_idx', right_on='index', right_index=True, how='right') 
    .drop('merge_idx', 1) 
    .dropna()) 

輸出:

manufacturer family model  name price     title 
    0  A  X foo A_foo_X  23 A_foo_X_blahblahblah 
    1  B  Y bar B_bar_Y  14 B_bar_Y_blahblahblah 
    2  C  Z baz C_baz_Z  19 C_baz_Z_blahblahblah 

這就是你想要的?

請注意,如果要保留B中的行,即使A中沒有匹配,只需在merge的末尾刪除.dropna()即可。

+0

非常感謝。如果我這樣使用[0] [0],則會出現以下錯誤: IndexError:('索引0超出軸0的邊界,大小爲0','發生在索引0'處) 如果我確實不能使用[0] [0],我merge_idx之看起來像這樣: merge_idx之 ([]) ([]) ([]) ([]) ([6327,6328,6343 ,7106],) ([497,3195,3196,3197,8966,11324],) ([],) ([],) ... 等。我認爲這意味着一些參賽者有多場比賽? 然後一旦我嘗試你的合併方法,我得到: TypeError:不可取的類型:'numpy.ndarray' – user3709260

+1

你能確認該代碼對我提供的示例數據有效嗎?如果這有效,那麼您的實際數據與我創建的示例數據有所不同。如果您可以使用您正在使用的一些實際數據或使用與您的實際用例類似的數據生成類似數據的代碼來更新您的文章,這將有所幫助,這與我在答案中嘗試做的內容類似。 –

+0

您的代碼可以正常使用示例數據。當然。請參閱更新和我的完整代碼。不知道在哪裏上傳,所以它在遠程服務器上。我非常感謝你的幫助。 – user3709260

相關問題