Как мне подсчитать вхождения слова в файле csv при определенных условиях?

#python #pandas #list #dataframe #count

#python #панды #Список #фрейм данных #подсчитать

Вопрос:

У меня есть файл data.csv как таковой (где данные — это слова)

 data
data1|data2|data3
data1|data2
data1|data4|data6
data2|data3
data4|data5|data6
data4
data5|data7
 

Я хочу прочитать, сколько раз data1 (например) присутствует, когда присутствует data2. Итак, когда и сколько раз в строках сосуществуют два данных, поскольку я хочу сформировать отношения между ними. Я знаю о методе счетчика, но меня не интересует просто подсчет экземпляров данных.

Как мне это решить? Создавать ли фрейм данных с помощью pd или использовать список?

(редактировать: максимальное количество столбцов в data.csv равно 6)

Желаемый результат будет примерно таким:

 data1-data2: 2
data1-data3: 1
data1-data4: 1
data1-data5: 0 
etc
 

сохранено в файл CSV

Комментарии:

1. Привет, Стивен, что ты уже пробовал? Не могли бы вы включить свой текущий подход?

2. Мне нечего показать для tbh. Я попытался преобразовать свой csv-файл в фрейм данных из 6 столбцов, затем преобразовать его в 2d-список и использовать условие для его чтения, но это с треском провалилось. У меня нет опыта синтаксического анализа данных, поэтому я пришел сюда.

3. ответы, приведенные ниже, которые используются itertools , довольно изящны

4. Не могли бы вы предоставить полный желаемый результат этой выборки данных? Существует много неясностей относительно того, какие корреляции вы ищете.

5. Да, я вижу, как это кажется запутанным. Например: результат data4-data5 должен быть равен 1. Для data5-data4 желаемый результат также должен быть равен 1, несмотря на то, что это не строка, содержащая эту комбинацию в таком порядке

Ответ №1:

Давайте попробуем с get_dummies помощью и combinations :

 from itertools import combinations

df = pd.read_csv('data.csv')
d = df['data'].str.get_dummies('|')

dct = {}
for x, y in combinations(g, r=2):
    dct[f'{x}:{y}'] = d[[x, y]].eq(1).all(1).sum()

# or with dict comprehension
# {'{}:{}'.format(*v): d[[*v]].eq(1).all(1).sum() for v in combinations(g, r=2)}
 

Подробные сведения:

Сначала прочитайте csv файл как фрейм данных pandas :

 print(df)
                data
0  data1|data2|data3
1        data1|data2
2  data1|data4|data6
3        data2|data3
4  data4|data5|data6
5              data4
6        data5|data7
 

Кодируйте значения в data виде фиктивных / индикаторных столбцов:

 print(d)
   data1  data2  data3  data4  data5  data6  data7
0      1      1      1      0      0      0      0
1      1      1      0      0      0      0      0
2      1      0      0      1      0      1      0
3      0      1      1      0      0      0      0
4      0      0      0      1      1      1      0
5      0      0      0      1      0      0      0
6      0      0      0      0      1      0      1
 

генерировать combinations столбцы индикаторов и использовать dict для хранения их частоты встречаемости вместе:


 print(dct)
{'data1:data2': 2,
 'data1:data3': 1,
 'data1:data4': 1,
 'data1:data5': 0,
 'data1:data6': 1,
 'data1:data7': 0,
 'data2:data3': 2,
  ...
  ...
 'data5:data7': 1,
 'data6:data7': 0}
 

Комментарии:

1. Приятное и элегантное решение. Тем не менее, вы можете расширить понимание этого dict, поскольку его, возможно, трудно читать и понимать, особенно учитывая, что это сайт о помощи менее опытным разработчикам, а не о code golf.

2. @HubertGrzeskowiak Спасибо за ваше предложение 🙂 .. но ИМХО после расширения его просто больше строк кода….

3. Дополнительные строки кода хороши, если они облегчают понимание и облегчают редактирование кода.

4. Он показал ошибку имени: имя ‘g’ не определено @ShubhamSharma

5. @HubertGrzeskowiak Не проблема .. отредактировал ответ

Ответ №2:

Вопрос очень неоднозначный, отсюда и так много разных ответов. Я предполагаю, что здесь вы имеете в виду подсчет комбинаций первого столбца и любого из следующих столбцов.

 import csv
from collections import Counter

counter = Counter()
with open('data.csv') as csvfile:
  reader = csv.reader(csvfile, delimiter='|')
  for line in reader:
    if line[0]:
      for fragment in line[1:]:
        entry = line[0]   '-'   fragment
        counter.update({entry: 1})

print(counter)
 

Вывод:

 Counter({'data1-data2': 2, 'data1-data3': 1, 'data1-data4': 1, 'data1-data6': 1, 'data2-data3': 1, 'data4-data5': 1, 'data4-data6': 1, 'data5-data7': 1})
 

РЕДАКТИРОВАТЬ 1:

Предполагая, что вам нужны какие-либо ненулевые комбинации существующих полей данных:

 import csv
from collections import Counter
from itertools import combinations

counter = Counter()
with open('data.csv') as csvfile:
  reader = csv.reader(csvfile, delimiter='|')
  for line in reader:
    counter.update(combinations(line, 2))

print(counter)
 

Вывод:

 Counter({('data1', 'data2'): 2, ('data2', 'data3'): 2, ('data4', 'data6'): 2, ('data1', 'data3'): 1, ('data1', 'data4'): 1, ('data1', 'data6'): 1, ('data4', 'data5'): 1, ('data5', 'data6'): 1, ('data5', 'data7'): 1})
 

РЕДАКТИРОВАТЬ 2:
Предполагая, что вы хотите, чтобы каждая ячейка данных была объединена с каждой другой ячейкой данных, включая те отношения, которые нигде не отображаются в одной строке:

 import csv
from collections import Counter
from itertools import combinations

counter = Counter()
unique = set()
with open('data.csv') as csvfile:
  reader = csv.reader(csvfile, delimiter='|')
  for line in reader:
    unique.update(line)
    counter.update(combinations(line, 2))
counter.update({entry: 0 for entry in combinations(unique, 2)})
print(counter)
 

Вывод:

 Counter({('data1', 'data2'): 2, ('data2', 'data3'): 2, ('data4', 'data6'): 2, ('data1', 'data3'): 1, ('data1', 'data4'): 1, ('data1', 'data6'): 1, ('data4', 'data5'): 1, ('data5', 'data6'): 1, ('data5', 'data7'): 1, ('data7', 'data5'): 0, ('data7', 'data2'): 0, ('data7', 'data4'): 0, ('data7', 'data6'): 0, ('data7', 'data1'): 0, ('data7', 'data'): 0, ('data7', 'data3'): 0, ('data5', 'data2'): 0, ('data5', 'data4'): 0, ('data5', 'data1'): 0, ('data5', 'data'): 0, ('data5', 'data3'): 0, ('data2', 'data4'): 0, ('data2', 'data6'): 0, ('data2', 'data1'): 0, ('data2', 'data'): 0, ('data4', 'data1'): 0, ('data4', 'data'): 0, ('data4', 'data3'): 0, ('data6', 'data1'): 0, ('data6', 'data'): 0, ('data6', 'data3'): 0, ('data1', 'data'): 0, ('data', 'data3'): 0})
 

Комментарии:

1. Извините, что не сформулировал это лучше. Я на самом деле забочусь о комбинациях любого рода между 2 данными. Вот что я имел в виду, говоря «сосуществовать». Порядок столбцов не имеет значения, но спасибо за ваше решение!

2. @Steven Это было забавное упражнение! Я добавил другие образцы, основанные на всех вещах, которые вы могли бы иметь в виду: D

3. Рад, что вам понравилось. Кстати, можно ли пропустить заголовок файла?

4. @Steven ты говоришь о заголовке в твоем CSV-файле? Это действительно зависит от того, есть ли у вас допустимый заголовок или нет. Образец данных в вашем сообщении не имеет допустимого заголовка — ему нужно будет определить имя для каждого столбца. Если вы просто хотите пропустить первую строку файла, вы можете добавить next(csvfile) ее непосредственно перед запуском программы чтения.

5. Я просто хотел пропустить первую строку (сработало как по волшебству) thx

Ответ №3:

Попробуйте выполнить следующее:

 import itertools

with open('yourfile.csv') as f:
    l=f.readlines()

l=[i[:-1] for i in l[:-1]]   [l[-1]] #remove 'n' at the end

res={}

for i in l:
    temp=i.split('|')
    pairs=[k for k in itertools.combinations(temp, 2)]
    for j in pairs:
        if j in res:
            res[j] =1
        elif j[::-1] in res:
            res[j[::-1]] =1
        else:
            res[j]=1
 

Вывод:

 >>>print(res)

{('data1', 'data2'): 2, ('data1', 'data3'): 1, ('data2', 'data3'): 2, ('data1', 'data4'): 1, ('data1', 'data6'): 1, ('data4', 'data6'): 2, ('data4', 'data5'): 1, ('data5', 'data6'): 1, ('data5', 'data7'): 1}
 

Если вам нужны пары, которые имеют 0 вхождений, вы можете сделать следующее:

 s={i for j in res.keys() for i in j}

allpairs=[i for i in itertools.combinations(s,2)]

for i in allpairs:
    if i not in res and (i[1], i[0]) not in res:
        res[i]=0