我的数据设置了一起工作或单独工作的人员列表。
每个项目都有一行,列中包含所有参与该项目的人员的姓名。如果第2列是给定行的第一个空列,那么它是一个独奏作业,如果第4列是给定行的第一个空列,则有3个人一起工作。
我的目标是找到哪些人一起工作,多少次,所以我想要数据集中的所有对,处理A与B一起使用与使用A的B相同。
由此创建一个正方形N x N,每个参与者标记列和行,并且单元格(A,B)和(B,A)将具有该对一起工作的次数,这将完成对于每一对。
我知道在Excel中使用“漂亮”的快捷方式,但我希望它能自动化,希望在Stata或Python中,以防万一添加或删除项目我只需单击重新运行即可每次都要重新做。
以逗号分隔方式的数据示例:
A
A,B
B,C,E
B,F
D,F
A,B,C
D,B
E,C,B
X,D,A
希望有所帮助!
布莱斯。 楼d 乙 F F,X,C C,F,d
答案 0 :(得分:1)
也许这样的事情会让你开始?
import csv
import collections
import itertools
grid = collections.Counter()
with open("connect.csv", "r", newline="") as fp:
reader = csv.reader(fp)
for line in reader:
# clean empty names
line = [name.strip() for name in line if name.strip()]
# count single works
if len(line) == 1:
grid[line[0], line[0]] += 1
# do pairwise counts
for pair in itertools.combinations(line, 2):
grid[pair] += 1
grid[pair[::-1]] += 1
actors = sorted(set(pair[0] for pair in grid))
with open("connection_grid.csv", "w", newline="") as fp:
writer = csv.writer(fp)
writer.writerow([''] + actors)
for actor in actors:
line = [actor,] + [grid[actor, other] for other in actors]
writer.writerow(line)
[编辑:修改为在Python 3.2下工作]
关键模块是(1)csv
,这使得读写csv文件更加简单; (2)collections
,它提供了一个名为Counter
的对象 - 就像defaultdict(int)
一样,如果你的Python没有Counter
就可以使用它,它是一个字典它会自动生成默认值,因此您不需要,默认计数为0;和(3)itertools
,它具有combinations
函数来获取所有对。
产生
,A,B,C,D,E,F,X
A,1,2,1,1,0,0,1
B,2,1,3,1,2,1,0
C,1,3,0,1,2,2,1
D,1,1,1,0,0,3,1
E,0,2,2,0,0,0,0
F,0,1,2,3,0,1,1
X,1,0,1,1,0,1,0
您可以使用itertools.product
使阵列构建更紧凑,但由于它只有一两行,我认为手动操作非常简单。
答案 1 :(得分:0)
如果我要保持这个项目一段时间,我会实现一个数据库,然后根据对该数据库的查询创建你正在谈论的矩阵。
你有一个Project
表(比方说),每个项目有一个记录,一个Actor
表,每人一行,一个Participant
表,每个项目有一个记录那个项目中的演员。 (每条记录都有ID
,ProjectID
和ActorID
。)
在您的示例中,您将拥有14条Project
条记录,7条Actor
条记录(A至F和X)以及31条Participant
条记录。
现在,通过此设置,每个单元格都是对此数据库的查询。
要重建矩阵,首先要在数据库中添加/更新/删除相应的记录,然后重新运行查询。
答案 2 :(得分:0)
我建议使用Python Pandas。它可以为您的邻接矩阵格式化提供灵活的解决方案,它也可以使任何统计计算更容易。您还可以直接将值矩阵提取到NumPy数组中,以便稍后在需要时对组群进行特征值分解或其他图论理论过程。
我假设你列出的示例数据被保存到一个名为projects_data.csv
的文件中(虽然它不需要实际上是.csv文件)。我还假设每个观察结果之间没有空行,但这只是文件组织的详细信息。
这是我的代码:
# File I/O part
import itertools, pandas, numpy as np
with open("projects_data.csv") as tmp:
lines = tmp.readlines()
lines = [line.split('\n')[0].split(',') for line in lines]
# Unique letters
s = set(list(itertools.chain(*lines)))
# Actual work.
df = pandas.DataFrame(
np.zeros((len(s),len(s))),
columns=sorted(list(s)),
index=sorted(list(s))
)
for line in lines:
if len(line) == 1:
df.ix[line[0],line[0]] += 1 # Single-person projects
elif len(line) > 1:
# Get all pairs in multi-person project.
tmp_pairs = list(itertools.combinations(line, 2))
# Append pair reversals to update (i,j) and (j,i) for each pair.
tmp_pairs = tmp_pairs + [pair[::-1] for pair in tmp_pairs]
for pair in tmp_pairs:
df.ix[pair[0], pair[1]] +=1
# Uncomment below if you don't want the list
# comprehension method for getting the reverals.
#df.ix[pair[1], pair[0]] +=1
# Final product
print df.to_string()
A B C D E F X
A 1 2 1 1 0 0 1
B 2 1 3 1 2 1 0
C 1 3 0 1 2 2 1
D 1 1 1 0 0 3 1
E 0 2 2 0 0 0 0
F 0 1 2 3 0 1 1
X 1 0 1 1 0 1 0
现在你可以免费做很多事情,比如查看每个参与者的项目合作伙伴总数(包括重复项):
>>> df.sum()
A 6
B 10
C 10
D 7
E 4
F 8
X 4
答案 3 :(得分:0)
我猜你在这些项目中没有成千上万的人在一起工作。这个实现非常简单。
fp = open('projects.cvs')
# counts how many times each pair worked together
pairs = {}
# each element of `project` is a person
for project in (p[:-1].split(',') for p in fp):
project.sort()
# someone is alone here
if len(project) == 1:
continue
# iterate over each pair
for i in range(len(project)):
for j in range(i+1, len(project)):
pair = (project[i], project[j])
# increase `pairs` counter
pairs[pair] = pairs.get(pair, 0) + 1
from pprint import pprint
pprint(pairs)
输出:
{('A', 'B'): 1,
('B', 'C'): 2,
('B', 'D'): 1,
('B', 'E'): 1,
('B', 'F'): 2,
('C', 'E'): 1,
('C', 'F'): 1,
('D', 'F'): 1}