Pandas:用特定指数匹配减去两个系列

2024-04-24 20:05:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个巨大的数据集,在那里我需要处理大量的数据,然后寻找1。一个实际的解决方案和2。快一点。在

我试着把我的问题尽可能地简化并转换成一个真实的例子,我希望它是清楚的。我很确定(至少我希望)这是熊猫身上的一个常见问题,而不是一个非常特殊的问题。在

假设我有两个工人在一个叫foo和{}的公司。有时他们在同一天工作,一遍又一遍地做同样的工作。我测量他们完成任务所需的时间(有时一天只做一次,有时几次)。在

我现在要找的是,如果他们两个在同一天工作,最短时间之间的差异。在

我尝试使用完整的方法,以便尽可能多地处理表(而不是遍历)。在

我目前的策略是:dayname分组,只保留最短的timeday和{},如果组大小为2(这意味着我有两个工人在同一天的数据)减去两次。在

最终目标:拥有最短时间差的Series。在

但是,我没有进行分组和筛选,所以现在我尝试为两个worker创建两个序列,然后计算时间差。在

下面是一个示例数据集:

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'])

以下是分组并只保留最短时间后的表格:

^{pr2}$

现在我只对第1天和第5天感兴趣,因为这是我仅有的两天拥有bar和{}的数据。所以如果我能过滤数据并在每组中减去两次,我就结束了,这样结果就是[-5, -7](从第1天开始:4-9天,第5天1-8天)。在

由于我不能进行过滤和减法,所以我尝试为这两个名称创建一个序列,并对每个名称进行减法,但是索引不匹配:

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})

在尝试减去每一个之后:

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

我的目标是这样的:

day time
1   -5
2   NaN
3   NaN
5   -7

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

这是否是一个快速完成的正确方法?在


Tags: 数据namedffootimebar序列nan
2条回答

我认为您可以将^{}aggfunc=min一起使用,然后减去bar和{}列:

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
^{pr2}$

我想你想做的是一个“内部”连接。此类型的联接执行要查找的索引匹配:

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

结果:

^{pr2}$

如果您希望NaN在只有一个工人工作的日子,您可以执行“outer”联接:

# 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

结果:

day
1    -5
2   NaN
3   NaN
5    -7
dtype: float64

相关问题 更多 >