删除有条件的行(多索引情况)
Delete rows with conditions (Multi-Index case)
我是 Stack Overflow 的新手,我有这个数据集:
df=pd.DataFrame({'ID': {0: 4, 1: 4, 2: 4, 3: 88, 4: 88, 5: 323, 6: 323},
'Step': {0: 'A', 1: 'Bar', 2: 'F', 3: 'F', 4: 'Bar', 5: 'F', 6: 'A'},
'Num': {0: 38, 1: 38, 2: 38, 3: 320, 4: 320, 5: 433, 6: 432},
'Date': {0: '2018-08-02',
1: '2018-12-02',
2: '2019-03-02',
3: '2017-03-02',
4: '2018-03-02',
5: '2020-03-04',
6: '2020-02-03'},
'Occurence': {0: 3, 1: 3, 2: 3, 3: 2, 4: 2, 5: 2, 6: 2}})
变量'ID'和'Step'是Multi-index.
我想做两件事:
第一个:
如果'Num'对于相同的'ID'不同,则删除该ID的行。
其次:
对于相同的ID,步骤'F'应该是最后一步(最近的日期)。如果不是,则删除此ID的行。
我遇到了一些困难,因为命令 df['Step'] 和 df['ID'] 不工作('ID' 和 'Step'最近 groupby() ).
的多索引原因
我试过在
上找到的 groupby(level=0)
但是我还有一些困难。
有人可以帮我吗?
预期输出:
df=pd.DataFrame({'ID': {0: 4, 1: 4, 2: 4},
'Step': {0: 'A', 1: 'Bar', 2: 'F'},
'Num': {0: 38, 1: 38, 2: 38},
'Date': {0: '2018-08-02',
1: '2018-12-02',
2: '2019-03-02',
'Occurence': {0: 3, 1: 3, 2: 3}})
ID 88 已被删除,因为步骤 'F' 不是最后一步(具有最新日期)。 ID 323 已被删除,因为 Num 433!=Num 432.
不知道我理解的对不对。
但是你可以试试这个
import os
import pandas as pd
sheet = pd.read_excel(io="you_file", sheet_name='sheet_name', na_filter=False, header=0 )
list_objects = []
for index,row in sheet.iterrows():
if (row['ID'] != index):
list_objects.append(row)
list_objects 将是 dict
的列表
- 按列对数据框进行分组
ID
Transform
Num
列使用 nunique
标识唯一值
- 使用
last
转换 Step
列以检查每组的最后一个值是否为 F
- 使用逻辑和组合布尔掩码并过滤行
g = df.groupby('ID')
m = g['Num'].transform('nunique').eq(1) & g['Step'].transform('last').eq('F')
print(df[m])
ID Step Num Date Occurence
0 4 A 38 2018-08-02 3
1 4 Bar 38 2018-12-02 3
2 4 F 38 2019-03-02 3
groupby
和 filter
的替代方法,但效率可能低于上述方法
df.groupby('ID').filter(lambda g: g['Step'].iloc[-1] == 'F' and g['Num'].nunique() == 1)
ID Step Num Date Occurence
0 4 A 38 2018-08-02 3
1 4 Bar 38 2018-12-02 3
2 4 F 38 2019-03-02 3
注意:如果 ID
和 Step
是 MultiIndex,您必须在使用上述建议的解决方案之前 reset
索引。
既然你说ID和Step都在索引中,那么我们可以这样:
df1[df1.sort_values('Date').groupby('ID')['Num']\
.transform(lambda x: (x.nunique() == 1) &
(x.index.get_level_values(1)[-1] == 'F'))]
输出:
Num Date Occurence
ID Step
4 A 38 2018-08-02 3
Bar 38 2018-12-02 3
F 38 2019-03-02 3
如何?
- 首先按'Date'
对数据框进行排序
- 然后按 ID 对数据帧进行分组
- 获取每组数据帧并使用 'Num' 列在布尔序列中进行转换,我们
首先获取 'Num' 中唯一元素的数量
组,如果该数字等于 1,则您知道在该组中
所有 'Num' 都相同,那就是 True
- 其次,我们得到 MultiIndex 的内层 (level=1) 和
我们使用 [-1] 索引检查最后一个值,如果该值是
等于 'F' 那么也有一个 True
使用 groupby 查找出现 1 次的行。我根据 groupby 结果的 ID return 删除数据框中的行。我排除了一次出现的 ID,不包括删除中的 ID。
df=pd.DataFrame({'ID': {0: 4, 1: 4, 2: 4, 3: 88, 4: 88, 5: 323, 6: 323},
'Step': {0: 'A', 1: 'Bar', 2: 'F', 3: 'F', 4: 'Bar', 5: 'F', 6: 'A'},
'Num': {0: 38, 1: 38, 2: 38, 3: 320, 4: 320, 5: 433, 6: 432},
'Date': {0: '2018-08-02',
1: '2018-12-02',
2: '2019-03-02',
3: '2017-03-02',
4: '2018-03-02',
5: '2020-03-04',
6: '2020-02-03'},
'Occurence': {0: 3, 1: 3, 2: 3, 3: 2, 4: 2, 5: 2, 6: 2}})
df.set_index(['ID','Step'],inplace=True)
print(df)
print("If 'Num' is different for the same 'ID', then delete the rows of this ID.")
#exclude id with single occurrences
grouped=df.groupby([df.index.get_level_values(0)]).size().eq(1)
labels=set([x for x,y in (grouped[grouped.values==True].index)])
filter=[x for x in df.index.get_level_values(0) if x not in labels]
grouped = df[df.index.get_level_values(0).isin(filter)].groupby([df.index.get_level_values(0),'Num']).size().eq(1)
labels=set([x for x,y in (grouped[grouped.values==True].index)])
if len(labels)>0:
df = df.drop(labels=labels, axis=0,level=0)
print(df)
输出:
Num Date Occurence
ID Step
4 A 38 2018-08-02 3
Bar 38 2018-12-02 3
F 38 2019-03-02 3
88 F 320 2017-03-02 2
Bar 320 2018-03-02 2
我是 Stack Overflow 的新手,我有这个数据集:
df=pd.DataFrame({'ID': {0: 4, 1: 4, 2: 4, 3: 88, 4: 88, 5: 323, 6: 323},
'Step': {0: 'A', 1: 'Bar', 2: 'F', 3: 'F', 4: 'Bar', 5: 'F', 6: 'A'},
'Num': {0: 38, 1: 38, 2: 38, 3: 320, 4: 320, 5: 433, 6: 432},
'Date': {0: '2018-08-02',
1: '2018-12-02',
2: '2019-03-02',
3: '2017-03-02',
4: '2018-03-02',
5: '2020-03-04',
6: '2020-02-03'},
'Occurence': {0: 3, 1: 3, 2: 3, 3: 2, 4: 2, 5: 2, 6: 2}})
变量'ID'和'Step'是Multi-index.
我想做两件事:
第一个:
如果'Num'对于相同的'ID'不同,则删除该ID的行。
其次:
对于相同的ID,步骤'F'应该是最后一步(最近的日期)。如果不是,则删除此ID的行。
我遇到了一些困难,因为命令 df['Step'] 和 df['ID'] 不工作('ID' 和 'Step'最近 groupby() ).
的多索引原因我试过在
但是我还有一些困难。
有人可以帮我吗?
预期输出:
df=pd.DataFrame({'ID': {0: 4, 1: 4, 2: 4},
'Step': {0: 'A', 1: 'Bar', 2: 'F'},
'Num': {0: 38, 1: 38, 2: 38},
'Date': {0: '2018-08-02',
1: '2018-12-02',
2: '2019-03-02',
'Occurence': {0: 3, 1: 3, 2: 3}})
ID 88 已被删除,因为步骤 'F' 不是最后一步(具有最新日期)。 ID 323 已被删除,因为 Num 433!=Num 432.
不知道我理解的对不对。 但是你可以试试这个
import os
import pandas as pd
sheet = pd.read_excel(io="you_file", sheet_name='sheet_name', na_filter=False, header=0 )
list_objects = []
for index,row in sheet.iterrows():
if (row['ID'] != index):
list_objects.append(row)
list_objects 将是 dict
的列表- 按列对数据框进行分组
ID
Transform
Num
列使用nunique
标识唯一值- 使用
last
转换Step
列以检查每组的最后一个值是否为F
- 使用逻辑和组合布尔掩码并过滤行
g = df.groupby('ID')
m = g['Num'].transform('nunique').eq(1) & g['Step'].transform('last').eq('F')
print(df[m])
ID Step Num Date Occurence
0 4 A 38 2018-08-02 3
1 4 Bar 38 2018-12-02 3
2 4 F 38 2019-03-02 3
groupby
和 filter
的替代方法,但效率可能低于上述方法
df.groupby('ID').filter(lambda g: g['Step'].iloc[-1] == 'F' and g['Num'].nunique() == 1)
ID Step Num Date Occurence
0 4 A 38 2018-08-02 3
1 4 Bar 38 2018-12-02 3
2 4 F 38 2019-03-02 3
注意:如果 ID
和 Step
是 MultiIndex,您必须在使用上述建议的解决方案之前 reset
索引。
既然你说ID和Step都在索引中,那么我们可以这样:
df1[df1.sort_values('Date').groupby('ID')['Num']\
.transform(lambda x: (x.nunique() == 1) &
(x.index.get_level_values(1)[-1] == 'F'))]
输出:
Num Date Occurence
ID Step
4 A 38 2018-08-02 3
Bar 38 2018-12-02 3
F 38 2019-03-02 3
如何?
- 首先按'Date' 对数据框进行排序
- 然后按 ID 对数据帧进行分组
- 获取每组数据帧并使用 'Num' 列在布尔序列中进行转换,我们 首先获取 'Num' 中唯一元素的数量 组,如果该数字等于 1,则您知道在该组中 所有 'Num' 都相同,那就是 True
- 其次,我们得到 MultiIndex 的内层 (level=1) 和 我们使用 [-1] 索引检查最后一个值,如果该值是 等于 'F' 那么也有一个 True
使用 groupby 查找出现 1 次的行。我根据 groupby 结果的 ID return 删除数据框中的行。我排除了一次出现的 ID,不包括删除中的 ID。
df=pd.DataFrame({'ID': {0: 4, 1: 4, 2: 4, 3: 88, 4: 88, 5: 323, 6: 323},
'Step': {0: 'A', 1: 'Bar', 2: 'F', 3: 'F', 4: 'Bar', 5: 'F', 6: 'A'},
'Num': {0: 38, 1: 38, 2: 38, 3: 320, 4: 320, 5: 433, 6: 432},
'Date': {0: '2018-08-02',
1: '2018-12-02',
2: '2019-03-02',
3: '2017-03-02',
4: '2018-03-02',
5: '2020-03-04',
6: '2020-02-03'},
'Occurence': {0: 3, 1: 3, 2: 3, 3: 2, 4: 2, 5: 2, 6: 2}})
df.set_index(['ID','Step'],inplace=True)
print(df)
print("If 'Num' is different for the same 'ID', then delete the rows of this ID.")
#exclude id with single occurrences
grouped=df.groupby([df.index.get_level_values(0)]).size().eq(1)
labels=set([x for x,y in (grouped[grouped.values==True].index)])
filter=[x for x in df.index.get_level_values(0) if x not in labels]
grouped = df[df.index.get_level_values(0).isin(filter)].groupby([df.index.get_level_values(0),'Num']).size().eq(1)
labels=set([x for x,y in (grouped[grouped.values==True].index)])
if len(labels)>0:
df = df.drop(labels=labels, axis=0,level=0)
print(df)
输出:
Num Date Occurence
ID Step
4 A 38 2018-08-02 3
Bar 38 2018-12-02 3
F 38 2019-03-02 3
88 F 320 2017-03-02 2
Bar 320 2018-03-02 2