#python #pandas #csv
Вопрос:
У меня есть CSV-файл, подобный этому:
w syn 0 abaca http://kaiko.getalp.org/dbnary/fra/Musa_textilis 1 abaca http://kaiko.getalp.org/dbnary/fra/chanvre_de_... 2 abaca http://kaiko.getalp.org/dbnary/fra/tagal 3 abaca http://kaiko.getalp.org/dbnary/fra/Musa_textilis 4 abaca http://kaiko.getalp.org/dbnary/fra/chanvre_de_... .. ... ... 95 abandon http://kaiko.getalp.org/dbnary/fra/apostasie 96 abandon http://kaiko.getalp.org/dbnary/fra/capitulation 97 abandon http://kaiko.getalp.org/dbnary/fra/cession_de_... 98 abandon http://kaiko.getalp.org/dbnary/fra/confiance 99 abandon http://kaiko.getalp.org/dbnary/fra/défection [100 rows x 2 columns] 6 {'abaca': 'tagal', 'abdomen': 'ventre', 'abricot': 'michemis', 'ADN': 'acide désoxyribonucléique', 'Indien': 'sauvage', 'abandon': 'défection'}
Я пытаюсь создать словарь, в котором каждое слово и его синоним. Я придумал этот код, но окончательный словарь содержит только один синоним слова, но, как вы можете видеть в файле csv, слово может иметь более одного синонима.
# read specific columns of csv file using Pandas df = pd.read_csv("sparql.csv", usecols = ["w","syn"]) #usecols = ["l","f","s","w","syn","synonyme"] print(df) liste_mot = df['w'].tolist() liste_mot = set(liste_mot) print(len(liste_mot)) liste_sys = [] dict_syn = {} for index, row in df.iterrows(): k, v = row sys = os.path.basename(v) if "_" in sys: sys = sys.split("_") sys = " ".join(sys) dict_syn[k] = sys else: dict_syn[k] = sys print(dict_syn)
То, что я хочу получить, — это каждое слово в качестве ключа и список всех их синонимов в качестве его значения, но пока я получаю только один синоним (syn) на слово (w), а не все из них.
Ответ №1:
Другой подход:
import os df = pd.read_csv("sparql.csv", usecols=["w","syn"]) df["syn_new"] = df.syn.map(os.path.basename).str.replace("_", " ") dict_syn = { key: group.syn_new.to_list() for key, group in df[["w", "syn_new"]].groupby("w") }
Результат для вашего образца:
{'abaca': ['Musa textilis', 'chanvre de ...', 'tagal', 'Musa textilis', 'chanvre de ...'], 'abandon': ['apostasie', 'capitulation', 'cession de ...', 'confiance', 'défection']}
Вы могли бы попробовать, если
df["syn_new"] = df.syn.str.rsplit("/", 1, expand=True)[1].str.replace("_", " ")
работает тоже, могло бы быть быстрее.
И, возможно, вам нужны не list
s, а set
s в качестве dict_syn
значений, чтобы избежать дублирования:
... key: set(group.syn_new.to_list()) ...
Ответ №2:
Вот рабочий пример, частично основанный на вашем коде. Синонимы помещаются в список:
from io import StringIO import pandas as pd text = """ w syn 0 abaca http://kaiko.getalp.org/dbnary/fra/Musa_textilis 1 abaca http://kaiko.getalp.org/dbnary/fra/chanvre_de_... 2 abaca http://kaiko.getalp.org/dbnary/fra/tagal 3 abaca http://kaiko.getalp.org/dbnary/fra/Musa_textilis 4 abaca http://kaiko.getalp.org/dbnary/fra/chanvre_de_... 95 abandon http://kaiko.getalp.org/dbnary/fra/apostasie 95 abandon http://kaiko.getalp.org/dbnary/fra/apostasie 96 abandon http://kaiko.getalp.org/dbnary/fra/capitulation 97 abandon http://kaiko.getalp.org/dbnary/fra/cession_de_... 98 abandon http://kaiko.getalp.org/dbnary/fra/confiance 99 abandon http://kaiko.getalp.org/dbnary/fra/défection """ # read in data df = pd.read_csv(StringIO(text), sep='s ') # get the synonym out of the url df['real_syn'] = df['syn'].str.extract('.*/(.*)') # dictionary to write results to result = {} # loop over every row of the dataframe for _, row in df[['w', 'real_syn']].iterrows(): word = row['w'] syn = row['real_syn'] # check if word is already in result dictionary and make sure words are not added twice if result.get(word) and syn not in result[word]: result[word] = result[word] [syn] else: # if word is not yet in dictionary, then add it a key, and add the synonym as a list result[word] = [syn] print(result)
Ответ №3:
Я не уверен, действительно ли ваш CSV имеет фиксированную ширину, или это просто хорошая распечатка.
Если вам не нужны Панды, стандартный CSV-модуль Python подходит для этой работы.
import csv import os import pprint from collections import defaultdict def syn_splitter(s): syn = os.path.basename(s) syn = syn.replace('_', ' ') return syn # So we can just start appending syns, without having to "prime" the dictionary with an empty list word_syn_map = defaultdict(list) with open('sample.csv', 'r', newline='') as f: reader = csv.reader(f) next(reader) # discard header for row in reader: w, syn = row syn = syn_splitter(syn) word_syn_map[w].append(syn) pprint.pprint(word_syn_map) # word_syn_map = dict(word_syn_map) if you want to get rid of the defaultdict wrapper
Я издевался над образцом.csv:
w,syn abaca,http://kaiko.getalp.org/dbnary/fra/Musa_textilis abaca,http://kaiko.getalp.org/dbnary/fra/tagal abaca,http://kaiko.getalp.org/dbnary/fra/Musa_textilis abandon,http://kaiko.getalp.org/dbnary/fra/apostasie abandon,http://kaiko.getalp.org/dbnary/fra/capitulation abandon,http://kaiko.getalp.org/dbnary/fra/confiance abandon,http://kaiko.getalp.org/dbnary/fra/défection
и я получил:
defaultdict(lt;class 'list'gt;, {'abaca': ['Musa textilis', 'tagal', 'Musa textilis'], 'abandon': ['apostasie', 'capitulation', 'confiance', 'défection']})