Python 大熊猫饲养:非明显群体

Python 大熊猫饲养:非明显群体,python,python-2.7,pandas,Python,Python 2.7,Pandas,我有一个数据帧: Time c_1 c_2 t1 x 1 t2 x 2 t3 y 1 t4 y 2 t5 1 x t6 2 x t7 1 y t8 2 y 我需要在不循环的情况下形成2列,以便: new_1:c_1.value出现在c_2中的下一个最早时间(例如,对于t1,new_1

我有一个数据帧:

Time    c_1     c_2   
 t1      x       1
 t2      x       2
 t3      y       1
 t4      y       2
 t5      1       x
 t6      2       x
 t7      1       y
 t8      2       y
我需要在不循环的情况下形成2列,以便:

  • new_1:c_1.value出现在c_2中的下一个最早时间(例如,对于t1,new_1=t5,因为c_1的值是“x”,而c_2中出现的下一个时间“x”是在t5)
  • new_2:c_2.value出现在c_1中的下一个最早时间(例如,对于t1,new_1=t5,因为c_2值为“1”,而c_1中出现的下一个时间“1”为t3)
因此,对于上述输入,输出应为:

Time    c_1     c_2    new_1     new_2
 t1      x       1       t5        t5
 t2      x       2       t5        t6
 t3      y       1       t7        t5            
 t4      y       2       t7        t6      
 t5      1       x       NaT       NaT
 t6      2       x       NaT       NaT
 t7      1       y       NaT       NaT
 t8      2       y       NaT       NaT

如何实现这一点?

这里有一个解决方案,它使用
apply()
和lambda函数从原始数据帧中为每行选择正确的数据

import pandas as pd

data = {'Time': pd.date_range('1/1/2000', periods=16, freq='D'),
        'c_1': ['x', 'x', 'y', 'y', '1', '2', '1', '2']*2,
        'c_2': ['1', '2', '1', '2', 'x', 'x', 'y', 'y']*2 }

df = pd.DataFrame(data)    
df['new_1'] = df.apply(lambda r: (df.Time[(df.Time>r.Time) & (df.c_2 == r.c_1)].head(1).reset_index(drop=True)), axis=1)
df['new_2'] = df.apply(lambda r: (df.Time[(df.Time>r.Time) & (df.c_1 == r.c_2)].head(1).reset_index(drop=True)), axis=1)
print(df)
输出为:

         Time c_1 c_2      new_1      new_2
0  2000-01-01   x   1 2000-01-05 2000-01-05
1  2000-01-02   x   2 2000-01-05 2000-01-06
2  2000-01-03   y   1 2000-01-07 2000-01-05
3  2000-01-04   y   2 2000-01-07 2000-01-06
4  2000-01-05   1   x 2000-01-09 2000-01-09
5  2000-01-06   2   x 2000-01-10 2000-01-09
6  2000-01-07   1   y 2000-01-09 2000-01-11
7  2000-01-08   2   y 2000-01-10 2000-01-11
8  2000-01-09   x   1 2000-01-13 2000-01-13
9  2000-01-10   x   2 2000-01-13 2000-01-14
10 2000-01-11   y   1 2000-01-15 2000-01-13
11 2000-01-12   y   2 2000-01-15 2000-01-14
12 2000-01-13   1   x        NaT        NaT
13 2000-01-14   2   x        NaT        NaT
14 2000-01-15   1   y        NaT        NaT
15 2000-01-16   2   y        NaT        NaT

apply
是通过
axis=1
完成的,因此它一次迭代一行。lambda函数仅选择数据帧中位于当前行之后且列中具有正确值的行。可能有多行符合这些条件。
head(1)
选择第一个匹配项,并且
reset_索引(drop=True)
确保返回的每个序列都有相同的索引(0),以便
apply()
将所有返回值放在一列中。

请准确显示您希望作为输出得到的
数据帧
是否有一种通用方法?如果我们将您的解决方案扩展到16个周期,并且值本身重复,那么只有前4个日期才会被您的解决方案填充。@Yeile我无法概括
groupby
版本,但我提出了一个版本,它使用
apply
并以一般方式处理重复值。