给定一个熊猫数据框,我将如何删除2行中2个特定列上具有相同值的所有行。就我而言,我有x,y and id
列。我想如果x-y
对在数据框中出现两次,以删除这两个之间的所有行。
示例:
import pandas as pd
df1 = pd.DataFrame({'x':[1,2,3,2,1,3,4],
'y':[1,2,3,4,3,3,4],
'id':[1,2,3,4,5,6,7]})
^ ^
如您所见,值对x=3,y=3
在数据框中出现两次,一次出现在id=3
,一次出现在id=6
。
我怎样才能发现这些行并将它们之间的所有行删除?
这样我就可以得到这个例子:
df1 = pd.DataFrame({'x':[1,2,3,4],
'y':[1,2,3,4],
'id':[1,2,3,7]})
数据帧也可能是这样,以便有更多的“重复项”,如我的下一个示例中的4,2对。我想发现外部重复项,以便通过删除它们之间的行来消除所有其他两次或更多出现的行。例如:
df1 = pd.DataFrame({'x':[1,2,3,4,1,4,3,4],
'y':[1,2,3,2,3,2,3,4],
'id':[1,2,3,4,5,6,7,8]})
^ ^ ^ ^
out in in out
#should become:
df1 = pd.DataFrame({'x':[1,2,3,4],
'y':[1,2,3,4],
'id':[1,2,3,8]})
对于我的示例,这应该导致某种形式的循环消除,我用数据框表示该图表。 我将如何实施?
答案 0 :(得分:2)
可能的解决方案之一:
让我们从创建DataFrame开始(这里我省略了必需的导入):
import turtle
import random
import math
def start():
myS = turtle.Screen()
myS.title("Random Walk")
border = 50
myS.setworldcoordinates(-border, -border, border, border)
def go(heading, step_size):
turtle.setheading(heading)
turtle.forward(step_size)
def random_walk(steps):
x = 0
y = 0
for i in range(steps):
angle = random.random()*2*math.pi
x = x + math.cos(angle)
y = y + math.sin(angle)
turtle.goto(x,y)
if __name__=="__main__":
start()
random_walk(100)
请注意,索引值是连续的数字(从0开始),以后将使用。
然后,我们必须找到重复的行,将所有实例标记为( keep = False ):
d = {'id': [1,2,3,4,5,6,7,8], 'x': [1,2,3,4,1,4,3,4], 'y': [1,2,3,2,3,2,3,4]}
df = pd.DataFrame(data=d)
然后将这些重复项分组在 x 和 y 上:
dups = df[df.duplicated(subset=['x', 'y'], keep=False)]
然后,应添加属于特定行的组的编号
到gr = dups.groupby(['x', 'y'])
,例如df
列。
grpNo
下一步是找到该行的第一个和最后一个索引,
被分组在第一组中(组号== 0)并保存在
df['grpNo'] = gr.ngroup()
和ind1
。
ind2
然后我们找到要删除的索引值列表:
ind1 = df[df['grpNo'] == 0].index[0]
ind2 = df[df['grpNo'] == 0].index[-1]
要执行实际的行删除,我们应该执行:
indToDel = df[(df.index > ind1) & (df.index <= ind2)].index
最后一步是删除df.drop(indToDel, inplace=True)
列,不再需要。
grpNo
结果是:
df.drop('grpNo', axis=1, inplace=True)
因此整个脚本可以如下:
id x y
0 1 1 1
1 2 2 2
2 3 3 3
7 8 4 4
答案 1 :(得分:0)
这对于您的两个示例都适用,尽管不确定是否可以概括您所想到的所有示例:
df1[df1['x']==df1['y']]