使用来自单独 table 的 ID 对从 table 中检索行
Retrieving rows from a table using pairs of IDs from a separate table
给定两个文件,
sentences_detailed.csv
包含 3 列(ID
、LANG
和 TEXT
)
links.csv
包含 2 列(ID1
和 ID2
),ID*
链接到 sentences_detailed.csv
中的 ID
列
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,以便使用 [=20] 中的 ID 对从 sentences_detailed.csv
中获取相应的 LANG
和 TEXT
列=]?
所需的输出 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 行。
在给定每个 links
行的源和目标 idx 的情况下,尝试过滤掉 sent_details
变得代价高昂。
必须有更好的 "pandas-ic" 方法来做到这一点。
完整数据集在 https://www.kaggle.com/alvations/how-to-get-parallel-sentences-from-tatoeba
Dark、Zero 和 COLDSPEED 的答案很好,但是当 sentences_detailed.csv 和 links.csv 中有重复项时,它们会抛出一些错误。
选项 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
一种快速的方法是分而治之,即
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))
您可以使用 links
中的 ID*
列作为 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.
给定两个文件,
sentences_detailed.csv
包含 3 列(ID
、LANG
和TEXT
)links.csv
包含 2 列(ID1
和ID2
),ID*
链接到sentences_detailed.csv
中的ID
列
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,以便使用 [=20] 中的 ID 对从 sentences_detailed.csv
中获取相应的 LANG
和 TEXT
列=]?
所需的输出 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 行。
在给定每个 links
行的源和目标 idx 的情况下,尝试过滤掉 sent_details
变得代价高昂。
必须有更好的 "pandas-ic" 方法来做到这一点。
完整数据集在 https://www.kaggle.com/alvations/how-to-get-parallel-sentences-from-tatoeba
Dark、Zero 和 COLDSPEED 的答案很好,但是当 sentences_detailed.csv 和 links.csv 中有重复项时,它们会抛出一些错误。
选项 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
一种快速的方法是分而治之,即
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))
您可以使用 links
中的 ID*
列作为 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.