Python 3.x 如何基于特定列中特定值的每次转换来选择数据帧中的行?

Python 3.x 如何基于特定列中特定值的每次转换来选择数据帧中的行?,python-3.x,pandas,dataframe,data-science,data-manipulation,Python 3.x,Pandas,Dataframe,Data Science,Data Manipulation,我有一个DataFrame,它的ID列和Value列只包含(0,1,2)。如果值列中有(0-1)或(1-2)的转换,我只想捕获这些行。必须分别为每个ID执行此过程 我尝试对ID执行groupby,并使用差异聚合函数。所以我可以取那些差值为1的行。但在某些情况下,它是失败的 df=df.loc[df['values'].isin([0,1,2])] df = df.sort_values(by=['Id']) df.value.diff() 给定数据帧: 索引UniqID值 一,   A.   

我有一个DataFrame,它的ID列和Value列只包含(0,1,2)。如果值列中有(0-1)或(1-2)的转换,我只想捕获这些行。必须分别为每个ID执行此过程

我尝试对ID执行groupby,并使用差异聚合函数。所以我可以取那些差值为1的行。但在某些情况下,它是失败的

df=df.loc[df['values'].isin([0,1,2])]
df = df.sort_values(by=['Id'])
df.value.diff()
给定数据帧:

索引UniqID值

一,   A.   一,

二,   A.   0

三,   A.   一,

四,   A.   0

五,   A.   一,

六,   A.   二,

七,   B   0

八,   B   二,

九,   B   一,

十,   B   二,

十一,   B   0

十二,   B   一,

十三,   C   0

十四,   C   一,

十五   C   二,

十六,   C   二,

预期产出:

二,   A.   0

三,   A.   一,

四,   A.   0

五,   A.   一,

六,   A.   二,

九,   B   一,

十,   B   二,

十一,   B   0

十二,   B   一,

十三,   C   0

十四,   C   一,

十五   C   二,

仅当存在从0-1或1-2的转换时才需要这些行


提前谢谢。

假设,转换严格从1->2和0->1进行。(此假设也有效。)

类似样本数据:

index,id,value
1,a,1
2,a,0
3,a,1
4,a,0
5,a,1
6,a,2
7,b,0
8,b,2
9,b,1
10,b,2
11,b,0
12,b,1
13,c,0
14,c,1
15,c,2
16,c,2
将其加载到数据帧中。 然后 使用以下代码:

def grp_trns(x):
    x['dif']=x.value.diff().fillna(0)
    return pd.DataFrame(list(x[x.dif==1]['index']-1)+list(x[x.dif==1]['index']))
target_index=df.groupby('id').apply(lambda x:grp_trns(x)).values.squeeze()
print(df[df['index'].isin(target_index)][['index', 'id','value']])
它根据假设给出了所需的数据帧:

     index id  value
1       2  a      0
2       3  a      1
3       4  a      0
4       5  a      1
5       6  a      2
8       9  b      1
9      10  b      2
10     11  b      0
11     12  b      1
12     13  c      0
13     14  c      1
14     15  c      2
编辑:要包含转换1->0,以下是更新的功能:

def grp_trns(x):
    x['dif']=x.value.diff().fillna(0)
    index1=list(x[x.dif==1]['index']-1)+list(x[x.dif==1]['index'])
    index2=list(x[(x.dif==-1)&(x.value==0)]['index']-1)+list(x[(x.dif==-1)&(x.value==0)]['index'])
    return pd.DataFrame(index1+index2)
对具有模式元组的组使用工作模式:

np.random.seed(123)

N = 100
d = {
    'UniqID': np.random.choice(list('abcde'), N),
    'Value': np.random.choice([0,1,2], N),
}
df = pd.DataFrame(d).sort_values('UniqID')
#print (df)



我的版本使用shift和diff()删除diff值等于0,2或-2的所有行

数据帧({'index':[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],'UniqId':['a','a','a','a','a','b','b','b','b','b','b','c','c','c','c','c','Value':[1,0,1,1,2,2,1,0,2]) df['diff']=np.NaN 对于df['UniqId'].unique()中的元素: df['diff'].loc[df['UniqId']==元素]=df.loc[df['UniqId']==元素]['Value'].diff() df['diff']=df['diff'].移位(-1) df=df.loc[(df['diff']!=-2)&(df['diff']!=2)&(df['diff']!=0)] 打印(df)
实际上正在等待关于2-1和1-2关系的更新

因此我们可以预期行是按索引排序的,这使得您引用的转换有意义?@jlandercy实际上是的,我对id进行了排序,还对附加的timestamp列进行了排序,该列提供了事件序列,我修改了数据和代码,以消除问题的复杂性,只专注于提问我遇到困难的特定部分。当你说转换是以1-2和2-1两种方式进行还是仅以增加方式进行?@Mayeulsgc严格地说是(0-1)还是(1-2)@shashashanksinghyadav-正确
8   B   2
?因为没有模式
1-2
您缺少行8@jezrael对于大数据,它是失败的(当我应用您的解决方案时,我得到了值序列1,2,1,1,0,1)…这里1,1不是必需的。@jezrael更准确地说,原始数据的一部分是(0,1,2,1,2),应用您的方法接收的输出是(0,1,2,2)…对于(1,0,1,0,1,2)…我给出了(1,1,0,1,2),这是我在检查时发现错误的地方。这意味着它排除了一些不应该排除的行。@jezrael是的,它们在同一组中。@jezrael我的意思是,在值列有0,1,0,1…的某些地方,代码返回0,1,1(跳过一个0),类似地,如果在某处1,2,1,2…,则代码返回(1,2,2)。当获取更大的数据集时,如果一个id中的值以0结尾,另一个id中的值以1开头,则您的解决方案将两者合并,并获取两行,即使它们来自不同的id。@ShashankSinghYadav更新了答案。请立即检查。仍然存在问题,例如…将0表示id a,将1表示id B。但根据我们的要求,代码应该删除它们,因为它们不是成对的。@ShashankSinghYadav如果您能给出示例/示例数据,以解决您面临的问题,则可以更快地重现以解决问题,并且可以减少误解的范围。(请在此处给出您试图描述的案例的所有3列。)@ShashankSinghYadav预期输出索引->7和8属于不同的组7的值为1,8的值为2,但此转换无效,因为它们属于不同的组。请检查您共享的输出行索引的有效性,似乎不符合要求。
pat = [(0, 1), (1, 2)]

a = np.array(pat)

s = (df.groupby('UniqID')['Value']
       .rolling(2, min_periods=1)
       .apply(lambda x: np.all(x[None :] == a, axis=1).any(), raw=True))

mask = (s.mask(s == 0)
         .groupby(level=0)
         .bfill(limit=1)
         .fillna(0)
         .astype(bool)
         .reset_index(level=0, drop=True))

df = df[mask]
print (df)
   UniqID  Value
99      a      1
98      a      2
12      a      1
63      a      2
38      a      0
41      a      1
9       a      1
72      a      2
64      b      1
67      b      2
33      b      0
68      b      1
57      b      1
71      b      2
10      b      0
8       b      1
61      c      1
66      c      2
46      c      0
0       c      1
40      c      2
21      d      0
74      d      1
15      d      1
85      d      2
6       d      1
88      d      2
91      d      0
83      d      1
4       d      1
34      d      2
96      d      0
48      d      1
29      d      0
84      d      1
32      e      0
62      e      1
37      e      1
55      e      2
16      e      0
23      e      1