首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >熊猫:用特定的指数匹配减去两个系列

熊猫:用特定的指数匹配减去两个系列
EN

Stack Overflow用户
提问于 2016-02-10 07:51:26
回答 2查看 3.7K关注 0票数 2

我有一个巨大的数据集,我需要处理大量的数字,并寻找1.一个实际的解决方案和2.一个快速的解决方案。

我试着把我的问题尽可能地简化并转移到一个真实的例子中,我希望它是清晰的。我很确定(至少我希望)这在潘达斯是一个常见的问题,而不是一个非常特殊的问题。

假设我在一家名为foobar的公司有两名员工。有时他们在同一天工作,一遍又一遍地做同样的工作。我测量他们完成任务所需的时间(有时一天只做一次,有时多次)。

我现在要找的是,如果他们在同一天工作的话,最短的时间之间的区别。

我试着做一个完整的方法,所以尽可能多地处理表(而不是迭代)。

我目前的策略是:将数据按dayname分组,如果组大小为2(这意味着我在同一天有两个工作人员的数据),则只保留最短的time / dayname

最终目标:有一个最短时间差异的Series

但是,我没有进行分组和过滤,所以现在我尝试为两个工作人员创建两个系列,然后计算时间差。

这里是一个示例数据集:

代码语言:javascript
复制
from StringIO import StringIO
import pandas as pd

raw_data="""day name time
1 foo 10
1 foo 9
1 bar 4
2 foo 12
2 foo 13
3 bar 3
3 bar 5
5 foo 8
5 bar 5
5 foo 9
5 bar 1
"""

df = pd.read_csv(StringIO(raw_data), sep=' ')

grouped_by_day_and_name = df.groupby(['day', 'name'])

在分组和只保留最短的时间之后,表的样子是这样的:

代码语言:javascript
复制
print grouped_by_day_and_name.agg({'time': min})

          time
day name      
1   bar      4
    foo      9
2   foo     12
3   bar      3
5   bar      1
    foo      8

现在我只对第一天和第五天感兴趣,因为那是我唯一有barfoo数据的日子。因此,如果我能够过滤数据并在每一组中两次减去数据,那么我就会完成,所以结果将是[-5, -7] (从1: 4-9,51-8开始)。

由于我无法过滤和减法,所以我尝试为两个名称创建一个系列,并减去每个名称,但是索引不匹配:

代码语言:javascript
复制
foo_best_times = df[df.name == 'foo'].groupby(['day', 'name']).agg({'time': min})
bar_best_times = df[df.name == 'bar'].groupby(['day', 'name']).agg({'time': min})

在试图减去每一个之后:

代码语言:javascript
复制
print foo_best_times - bar_best_times

          time
day name      
1   bar    NaN
    foo    NaN
2   foo    NaN
3   bar    NaN
5   bar    NaN
    foo    NaN

我的目标是这样的:

代码语言:javascript
复制
day time
1   -5
2   NaN
3   NaN
5   -7

如何通过只匹配day作为索引来减去这两个序列?

这是快速完成任务的正确方法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-02-10 08:18:19

我认为您可以将pivot_tableaggfunc=min一起使用,然后再使用barfoo减法列。

代码语言:javascript
复制
from StringIO import StringIO 
import pandas as pd

raw_data="""day name time
1 foo 10
1 foo 9
1 bar 4
2 foo 12
2 foo 13
3 bar 3
3 bar 5
5 foo 8
5 bar 5
5 foo 9
5 bar 1
"""

df = pd.read_csv(StringIO(raw_data), sep=' ')
print df
    day name  time
0     1  foo    10
1     1  foo     9
2     1  bar     4
3     2  foo    12
4     2  foo    13
5     3  bar     3
6     3  bar     5
7     5  foo     8
8     5  bar     5
9     5  foo     9
10    5  bar     1
代码语言:javascript
复制
df = df.pivot_table(index='day', columns='name', values='time', aggfunc=min)

print df
name  bar  foo
day           
1       4    9
2     NaN   12
3       3  NaN
5       1    8


print df['bar'] - df['foo']
1    -5
2   NaN
3   NaN
5    -7
dtype: float64
票数 2
EN

Stack Overflow用户

发布于 2016-02-10 08:12:12

我认为你想做的是“内在”的加入。这种类型的联接执行您正在寻找的索引匹配:

代码语言:javascript
复制
from StringIO import StringIO
import pandas as pd

raw_data="""day name time
1 foo 10
1 foo 9
1 bar 4
2 foo 12
2 foo 13
3 bar 3
3 bar 5
5 foo 8
5 bar 5
5 foo 9
5 bar 1
"""

df = pd.read_csv(StringIO(raw_data), sep=' ')

# Split the dataset into the two workers
foo = df.query('name == "foo"')
bar = df.query('name == "bar"')

# Find for each day the shortest working time
foo = foo.groupby('day').agg('min')
bar = bar.groupby('day').agg('min')

# Perform an inner join of the two workers, this only keeps days
# where both workers have been working
joined = foo.join(bar, how='inner', lsuffix='_foo', rsuffix='_bar')

# Compute the difference in minimum working times
diff = joined['time_bar'] - joined['time_foo']

print diff

结果:

代码语言:javascript
复制
day
1    -5
5    -7
dtype: int64

如果您希望NaN在只有一名员工工作的日子里工作,您可以执行“外部”连接:

代码语言:javascript
复制
# Perform an outer join of the two workers, this only keeps days
# where both workers have been working
joined = foo.join(bar, how='outer', lsuffix='_foo', rsuffix='_bar')

# Compute the difference in minimum working times
diff = joined['time_bar'] - joined['time_foo']

print diff

结果:

代码语言:javascript
复制
day
1    -5
2   NaN
3   NaN
5    -7
dtype: float64
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35309556

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档