代码之家  ›  专栏  ›  技术社区  ›  alvas

使用单独表中的ID对从表中检索行

  •  1
  • alvas  · 技术社区  · 8 年前

    给定两个文件,

    • sentences_detailed.csv 包含3列( ID , LANG 和 TEXT )
    • links.csv 包含2列( ID1 和 ID2 ),则 ID* 链接到 身份证件 中的列 句子\u详细。csv

    的样本 句子\u详细。csv :

    ID LANG TEXT
    123 eng I want you to meet my parents.
    456 eng I'm on your side.
    789 eng I did not want to alarm you. 
    567 kor 부모님을 만나길 원해.
    2352 jpn 私はあなたの側にいます。
    

    和样品 链接。csv :

    ID1 ID2
    123 567
    2352 456
    

    如何创建一个新的数据帧,以便获得相应的 朗 和 文本 列来自 句子\u详细。csv 使用中的ID对 链接。csv ?

    所需的输出数据帧应如下所示:

    ID1 ID2 LANG1 LANG2 TEXT1 TEXT2
    123 567 eng kor I want you to meet my parents. 부모님을 만나길 원해.
    2352 456 jpn eng 私はあなたの側にいます。I'm on your side.
    

    我试过这个:

    sent_details_csv = """ID    LANG    TEXT
    123 eng I want you to meet my parents.
    456 eng I'm on your side.
    789 eng I did not want to alarm you. 
    567 kor 부모님을 만나길 원해.
    2352    jpn 私はあなたの側にいます。"""
    
    links_csv = """ID1  ID2
    123 567
    2352    456
    """
    
    from io import StringIO
    
    sent_details = pd.read_csv(StringIO(sent_details_csv), sep='\t')
    links = pd.read_csv(StringIO(links_csv), sep='\t')
    
    for idx, row in links.iterrows():
        src_idx, trg_idx = row['ID1'], row['ID2']
    
        try:
            src = sent_details[sent_details['ID'] == src_idx][['TEXT', 'LANG']].iloc[0]
            trg = sent_details[sent_details['ID'] == trg_idx][['TEXT', 'LANG']].iloc[0]
        except: 
            continue
    
        print('\t'.join(map(str, [src_idx, trg_idx, src['LANG'], trg['LANG'], src['TEXT'], trg['TEXT']])))
    

    上述代码适用于小数据集,但实际 句子\u详细。csv 超过6000000行 链接。csv 约13000000行。

    正在尝试筛选出 sent_details 为每个给定一个源和目标idx links row GET变得昂贵。

    必须有一个更好的更“熊猫ic”的方法来做到这一点。


    完整数据集已打开 https://www.kaggle.com/alvations/how-to-get-parallel-sentences-from-tatoeba

    Dark、Zero和COLDSPEED的答案都很好,但如果句子中有重复的话,请详细说明。csv和链接。csv,它们会抛出一些错误。

    3 回复  |  直到 8 年前
        1
  •  3
  •   Bharath M Shetty    8 年前

    一种快速的方法是分而治之,即

    one = df[df['ID'].isin(links['ID1'])].copy()
    two = df[df['ID'].isin(links['ID2'])].copy()
    
    two['NEW_ID'] = two['ID'].map(links.set_index('ID2')['ID1'])
    
    one.merge(two,left_on='ID',right_on='NEW_ID',suffixes=('1', '2'))
    
         ID1 LANG1                         TEXT1       ID2  LANG2       TEXT2      NEW_ID  
    0   123    eng     I want you to meet my parents.  567    kor  부모님을 만나길 원해.     123  
    1  2352    jpn             私はあなたの側にいます。    456    eng  I'm on your side.    2352 
    

    由于存在重复ID,映射无法工作,因此可以使用双重合并,即

    one.merge(two.merge(links,left_on='ID',right_on='ID2'),left_on='ID',right_on='ID1',suffixes=('1', '2')))
    
     ID1 LANG1                           TEXT1  ID2 LANG2              TEXT2  \
    0   123   eng  I want you to meet my parents.  567   kor       부모님을 만나길 원해.   
    1  2352   jpn                    私はあなたの側にいます。  456   eng  I'm on your side.   
    
        ID1  ID2  
    0   123  567  
    1  2352  456  
    

    基于实际数据,您可以简单地交叉合并相同的数据帧,因为您具有相同的列名,即

    sec = sent_details.merge(links)
    
    sec.merge(sec, left_on=['Sentence id','Translation id'],right_on=['Translation id','Sentence id'], suffixes=(1,2))
    
        2
  •  2
  •   Zero    8 年前

    选项1] 使用 merge 和 concat

    In [328]: pd.concat([df2[['ID'+x]].merge(df1.add_suffix(x)) for x in ['1', '2']], axis=1)
    Out[328]:
        ID1 LANG1                           TEXT1  ID2 LANG2              TEXT2
    0   123   eng  I want you to meet my parents.  567   kor       부모님을 만나길 원해.
    1  2352   jpn                    私はあなたの側にいます。  456   eng  I'm on your side.
    

    选项2]

    一种方法是使用 map 具有 set_index

    In [307]: df11 = df1.set_index('ID')
    
    In [308]: for c in ['LANG', 'TEXT']:
         ...:     for x in ['1', '2']:
         ...:         df2[c + x] = df2['ID' + x].map(df11[c])
         ...:
    
    In [309]: df2
    Out[309]:
        ID1  ID2 LANG1 LANG2                           TEXT1              TEXT2
    0   123  567   eng   kor  I want you to meet my parents.       부모님을 만나길 원해.
    1  2352  456   jpn   eng                    私はあなたの側にいます。  I'm on your side.
    

    细节

    In [303]: df1
    Out[303]:
         ID LANG                            TEXT
    0   123  eng  I want you to meet my parents.
    1   456  eng               I'm on your side.
    2   789  eng   I did not want to alarm you.
    3   567  kor                    부모님을 만나길 원해.
    4  2352  jpn                    私はあなたの側にいます。
    
    In [304]: df2
    Out[304]:
        ID1  ID2
    0   123  567
    1  2352  456
    
        3
  •  1
  •   cs95 abhishek58g    8 年前

    您可以使用 ID* 中的列 links 作为 sent_details 列,使用 loc -

    df1 = df1.set_index('ID')
    

    i = df1.loc[df2.ID1].reset_index().add_suffix('_1')
    j = df1.loc[df2.ID2].reset_index().add_suffix('_2')
    
    pd.concat([i, j], 1)
    
       ID_1 LANG_1                          TEXT_1  ID_2 LANG_2                 TEXT_2
    0   123    eng  I want you to meet my parents.   567    kor       부모님을 만나길 원해.
    1  2352    jpn          私はあなたの側にいます。   456    eng       I'm on your side.
    

    在哪里-

    df1 = sent_details
    

    和

    df2 = links   
    

    如果希望结果按照您的要求进行排序,请使用 sort_index -

    v = pd.concat([i, j], 1)
    v.reindex(columns=sorted(v.columns, key=lambda x: x.split('_')[0]))
    
       ID_1  ID_2 LANG_1 LANG_2                          TEXT_1                 TEXT_2
    0   123   567    eng    kor  I want you to meet my parents.       부모님을 만나길 원해.
    1  2352   456    jpn    eng           私はあなたの側にいます。      I'm on your side.