使用来自单独表

时间:2017-12-28 09:58:55

标签: python pandas csv linked-tables

给出两个文件,

  • sentences_detailed.csv包含3列(IDLANGTEXT
  • links.csv包含2列(ID1ID2),ID*ID sentences_detailed.csv列相关联>

sentences_detailed.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

如何创建新的DataFrame,以便使用LANG中的ID对从TEXT获取相应的sentences_detailed.csvlinks.csv列?< /强>

所需的输出DataFrame应如下所示:

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']])))

上面的代码适用于小型数据集,但实际sentences_detailed.csv为6,000,000多行,links.csv为~13,000,000行。

如果给定每个sent_details行的源和目标idx,尝试过滤links会变得很昂贵。

必须有更好的“pandas-ic”方式才能做到这一点。

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

Dark,Zero和COLDSPEED的答案很好但是当在sentence_detailed.csv和links.csv中出现重复时,它们会产生一些错误。

3 个答案:

答案 0 :(得分:3)

一种快速的做法是通过划分和合并,即

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))

答案 1 :(得分:2)

选项1] 使用mergeconcat

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]

一种方法是将mapset_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

答案 2 :(得分:1)

您可以使用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.