我应该如何构造和访问数据表,以便在Python 3.5中轻松比较子集? 有没有一种更快、更像蟒蛇的方法 什么是 生成此警告UserWarning:Boolean系列键将 重新编制索引以匹配数据帧索引。“数据帧索引”,用户警告 我应该关心它吗

我应该如何构造和访问数据表,以便在Python 3.5中轻松比较子集? 有没有一种更快、更像蟒蛇的方法 什么是 生成此警告UserWarning:Boolean系列键将 重新编制索引以匹配数据帧索引。“数据帧索引”,用户警告 我应该关心它吗,python,python-3.x,pandas,dataframe,Python,Python 3.x,Pandas,Dataframe,我有一个csv文件,有三列:组织、月份、个人 | org | month | person | | --- | ---------- | ------ | | 1 | 2014-01-01 | 100 | | 1 | 2014-01-01 | 200 | | 1 | 2014-01-02 | 200 | | 2 | 2014-01-01 | 300 | 我已将其读入pandas.core.frame.DataFrame中,其中包含: data

我有一个csv文件,有三列:组织、月份、个人

| org |    month   | person |
| --- | ---------- | ------ |
|   1 | 2014-01-01 |    100 |
|   1 | 2014-01-01 |    200 |
|   1 | 2014-01-02 |    200 |
|   2 | 2014-01-01 |    300 |
我已将其读入pandas.core.frame.DataFrame中,其中包含:

data = pd.read_csv('data_base.csv', names=['month', 'org', 'person'], skiprows=1)
最终目标是比较两个连续时段的人员交叉点与第一个时段的人员集合

org: 1, month: 2014-01-01, count(intersection((100, 200), 200)) / len(set(100, 200)) == 0.5
编辑:我用它工作:

import pandas as pd
import sys

data = pd.read_csv('data_base.csv', names=['month', 'org', 'person'], skiprows=1)
data.sort_values(by=['org', 'month', 'person'])

results = {}
for _org in set(data.org):
    results[_org] = {}
    months = sorted(list(set(data[data.org == _org].month)))
    for _m1, _m2 in zip(months, months[1:]):
        _s1 = set(data[data.org == _org][data.month == _m1].person)
        _s2 = set(data[data.org == _org][data.month == _m2].person)
        results[_org][_m1] = float(len(_s1 & _s2) / len(_s1))
        print(str(_org) + '\t' + str(_m1) + '\t' + str(_m2) + '\t' + str(round(results[_org][_m1], 2)))
        sys.stdout.flush()
产生如下输出:

UserWarning: Boolean Series key will be reindexed to match DataFrame index. "DataFrame index.", UserWarning
5640    2014-01-01  2014-02-01  0.75
5640    2014-02-01  2014-03-01  0.36
5640    2014-03-01  2014-04-01  0.6
...
df['one'] = 1
df = df.set_index(['org','month','person']).unstack('person')
numer = ((df==df.shift(-1)) & (df.notnull())).sum(axis=1)
denom = df.notnull().sum(axis=1)

df['numer'] = numer
df['denom'] = denom
df['ratio'] = numer / denom

               one             numer denom     ratio
person         100 200 300 400                      
org month                                           
1   2014-01-01   1   1 NaN NaN     1     2  0.500000
    2014-01-02 NaN   1 NaN NaN     0     1  0.000000
    2014-01-03   1 NaN   1 NaN     2     2  1.000000
    2014-01-04   1   1   1 NaN     2     3  0.666667
2   2014-01-01   1   1 NaN NaN     0     2  0.000000
    2014-01-02 NaN NaN   1   1     0     2  0.000000
    2014-01-03   1 NaN NaN NaN     1     1  1.000000
    2014-01-04   1   1 NaN NaN     0     2  0.000000

但它确实很慢,而且有点难看。…按照目前的速度,我的信封背面计算估计,两年一批数据大约需要22个小时。

不可否认,我从未使用过熊猫,所以这可能不是惯用方法。这只是使用基本的Python结构

import collections
org_month_dict = collections.defaultdict(set)

# put the data into a simple, indexed data structure
for index, row in data.iterrows():
    org_month_dict[row['org'], row['month']].add(row['person'])

orgs = set(data.org)
months = sorted(set(data.months))
for org in orgs:
    for mindex in range(len(months)-1):
        m1 = months[mindex]
        m2 = months[mindex+1]
        print org_month_dict[org, m2] & org_month_dict[org, m1] # persons in common between month 1 and 2

这将在
org\u month\u dict
中创建一个按组织和月份索引的“缓存”查找表,从而避免您在内部循环中执行昂贵的
数据[data.org==\u org][data.month==\u m1]
查找。它的运行速度应该比您的原始代码快得多。

我不必在这里忽略熊猫。这取决于几件事。我不认为pandas是一种真正紧凑的数据存储方式,尽管它有自动压缩和稀疏存储选项,这在很大程度上缓解了这一问题。我希望速度是相当合理的,但你真的必须在你的数据上测试它才能确定

在我看来,它确实提供了一种更方便的方式来存储数据,还提供了处理日期的方便方式。完成后,可以以表格形式输出结果

首先,我将稍微扩展一下数据,以更好地演示这些问题

    org       month  person
0     1  2014-01-01     100
1     1  2014-01-01     200
2     1  2014-01-02     200
3     1  2014-01-03     300
4     1  2014-01-03     100
5     1  2014-01-04     200
6     1  2014-01-04     100
7     1  2014-01-04     300
8     2  2014-01-01     100
9     2  2014-01-01     200
10    2  2014-01-02     300
11    2  2014-01-02     400
12    2  2014-01-03     100
13    2  2014-01-04     200
14    2  2014-01-04     100
然后,你可以这样做:

UserWarning: Boolean Series key will be reindexed to match DataFrame index. "DataFrame index.", UserWarning
5640    2014-01-01  2014-02-01  0.75
5640    2014-02-01  2014-03-01  0.36
5640    2014-03-01  2014-04-01  0.6
...
df['one'] = 1
df = df.set_index(['org','month','person']).unstack('person')
numer = ((df==df.shift(-1)) & (df.notnull())).sum(axis=1)
denom = df.notnull().sum(axis=1)

df['numer'] = numer
df['denom'] = denom
df['ratio'] = numer / denom

               one             numer denom     ratio
person         100 200 300 400                      
org month                                           
1   2014-01-01   1   1 NaN NaN     1     2  0.500000
    2014-01-02 NaN   1 NaN NaN     0     1  0.000000
    2014-01-03   1 NaN   1 NaN     2     2  1.000000
    2014-01-04   1   1   1 NaN     2     3  0.666667
2   2014-01-01   1   1 NaN NaN     0     2  0.000000
    2014-01-02 NaN NaN   1   1     0     2  0.000000
    2014-01-03   1 NaN NaN NaN     1     1  1.000000
    2014-01-04   1   1 NaN NaN     0     2  0.000000

我在这里忽略了一些细节,比如Org1和Org2之间的断点,但是您可以添加一个groupby来处理这个问题。类似地,您可能需要添加代码来处理无人在场的日子,并且有一些方法可以解决这一问题。

无论如何,他不应该在这里使用Pandas(请参阅我的评论),因此这是一个使用正确方法的极好答案。感谢您提供有关Pandas在切片速度方面的缺点的信息。我查阅了如何将csv文件读入Python,示例中使用了Pandas的read_csv函数,所以我就是这样做的。访问单个元素的时间大约为10-100微秒,是字典查找的1000倍(低于50纳秒)。折衷是,pandas非常适合于使用大数据进行完整的数据帧或按列计算:长的开始时间与极快的矢量化计算可以很好地折衷。在这里,您可以有效地逐元素计算并从Pandas类型转换,这意味着Pandas虽然非常优秀,但并不适合此任务。您可以解释一下
(df==df.shift(-1))
行吗?这是一个布尔值,显示哪些单元格与上面的单元格匹配。只需把
numer
行打印出来,就可以更好地了解它在做什么。