Python 3.x 如何基于特定列中特定值的每次转换来选择数据帧中的行?
我有一个DataFrame,它的ID列和Value列只包含(0,1,2)。如果值列中有(0-1)或(1-2)的转换,我只想捕获这些行。必须分别为每个ID执行此过程 我尝试对ID执行groupby,并使用差异聚合函数。所以我可以取那些差值为1的行。但在某些情况下,它是失败的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.
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