#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