1

我的数据集列出了一起工作或单独工作的人。

我对每个项目都有一行,并在列中列出了参与该项目的所有人员的姓名。如果第 2 列是给定一行的第一个空列,那么它是一个单独的工作,如果第 4 列是给定一行的第一个空列,那么有 3 个人一起工作。

我的目标是找出哪些人一起工作过,以及合作过多少次,所以我想要数据集中的所有对,将 A 与 B 一起工作与 B 与 A 一起工作一样。

由此,将创建一个正方形 N x N,每个参与者都标记列和行,并且在单元格 (A,B) 和 (B,A) 中,该对将一起工作多少次,这将对每一对完成.

我知道在 Excel 中执行此操作的“非常”快速的方法,但我希望它自动化,希望在 Stata 或 Python 中,以防万一添加或删除项目,我只需单击 1 次重新运行,而不必重新-每次都这样做。

以逗号分隔的数据示例:

A
A,B
B,C,E
B,F
D,F
A,B,C
D,B
E,C,B
X,D,A

希望有帮助!

布莱斯。F,D B F F,X,C C,F,D

4

4 回答 4

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,它提供了一个名为 a 的对象Counter-- 就像 a 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来使构建阵列更加紧凑,但由于它只有一两行,我认为手动完成它很简单。

于 2012-09-29T18:56:37.820 回答
0

如果我要保留这个项目一段时间,我会实现一个数据库,然后通过对该数据库的查询创建您正在谈论的矩阵。

您有一个Project表(比方说),每个项目有一条记录,一个Actor表每人一行,还有一个Participant表,其中每个项目的每个参与者都有一个记录。(每条记录都有一个ID、一个ProjectID和一个ActorID。)

在您的示例中,您将有 14Project条记录、7Actor条记录(A 到 F 和 X)和 31Participant条记录。

现在,通过这种设置,每个单元格都是对该数据库的查询。

要重建矩阵,首先您要在数据库中添加/更新/删除适当的记录,然后重新运行查询。

于 2012-09-29T18:56:29.303 回答
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
于 2012-09-29T19:34:31.407 回答
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}
于 2012-09-29T21:32:12.723 回答