Python 如何找到按分组的两列数据帧行的交点,并从包含该值的单元格中删除该值?
我有一个数据框,如下所示:Python 如何找到按分组的两列数据帧行的交点,并从包含该值的单元格中删除该值?,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个数据框,如下所示: name teamA teamB foo a b foo b c foo c b bar a e bar a d ... 我想分别查找每个名称的行交叉点,但同时查找teamA和teamB列的行交叉点。然后删除包含该交点值的单元格的值。 在本例中,对于名称“foo”,行的交点将是“b”,而对于名称“bar”将是“a”。 因此,删除此交点值后的数据帧如下所示: na
name teamA teamB
foo a b
foo b c
foo c b
bar a e
bar a d
...
我想分别查找每个名称的行交叉点,但同时查找teamA和teamB列的行交叉点。然后删除包含该交点值的单元格的值。
在本例中,对于名称“foo”,行的交点将是“b”,而对于名称“bar”将是“a”。
因此,删除此交点值后的数据帧如下所示:
name teamA teamB
foo a " "
foo " " c
foo c " "
bar " " e
bar " " d
...
最近,我尝试将teamA和teamB作为一个专栏,以示例团队命名
name teams
foo [a, b]
foo [b, c]
foo [c, b]
...
之后我想得到
name teams
foo [a, " "]
foo [" ", c]
foo [c, " "]
...
但我发现更推荐将其分为两列,我发现答案很有趣,但我不知道如何将其应用于分组数据帧。
(请参阅“筛选多个列”部分和“保留至少有一列为真的行”)。
如该例所示:
dataframe[['teamA', 'teamB']].isin('b').any(axis=1)
0 True
1 True
2 True
3 True
dtype: bool
其中“b”将是我将迭代的值(团队)之一。在每次迭代之后,如果整列为True,我将从每行的列teamA或teamB中删除该值,并继续到另一个组
我得到的错误是:
Cannot access callable attribute 'isin' of 'DataFrameGroupBy' objects, try using the 'apply' method
及
我们可以做
melt
,然后放下复制品,然后pivot
将其放回原处
s=df.reset_index().melt(['index','name']).\
drop_duplicates(['name','value'],keep=False).\
pivot_table(index=['index','name'],columns='variable',values='value',aggfunc='first').\
fillna('').reset_index(level=1)
s['team']=list(zip(s.teamA,s.teamB))
s
Out[102]:
variable name teamA teamB team
index
0 foo a (a, )
1 foo c (, c)
2 foo d (, d)
3 bar e (, e)
4 bar d (, d)
也许不如@温约本漂流好,但你可以考虑使用一个非常灵活的自定义函数
将熊猫作为pd导入
df=pd.DataFrame({“name”:[“foo”]*3+[“bar”]*2,
“teamA”:[“a”、“b”、“b”、“a”、“a”],
“团队b”:[“b”、“c”、“d”、“e”、“d”]})
def fun(x):
toRemove=列表(设置(x[“teamA”].值)。交叉点(x[“teamB”]))
对于[“teamA”、“teamB”]中的列:
x[col]=np.where(x[col].isin(toRemove),“”,x[col])
返回x
df.groupby(“名称”).apply(乐趣)
哪个输出是:
name teamA teamB
0福阿
1富c
二福
3巴
4巴
+。
示例数据帧:
print(df)
name teamA teamB
0 foo a b
1 foo b c
2 foo b d
3 bar a e
4 bar a d
5 bar b a
然后使用+
join
和split
获得teams
列:
new_df['teams']=new_df[['teamA','teamB']].apply(lambda x: ','.join(x).split(','),axis=1)
print(new_df)
name teamA teamB teams
0 foo a [a, ]
1 foo c [ , c]
2 foo d [ , d]
3 bar e [ , e]
4 bar d [ , d]
5 bar b [b, ]
尝试使用
groupby
并应用stack
,drop\u duplicates
,unstack
,fillna
(df[['teamA', 'teamB']].groupby(df.name, sort=False)
.apply(lambda x: x.stack().drop_duplicates(keep=False))
.unstack().fillna('').reset_index('name'))
Out[93]:
name teamA teamB
0 foo a
1 foo c
2 foo d
3 bar e
4 bar d
在我昨天编辑了我的问题之后。。。 这是我的数据帧(
df
):
这就是解决方案:
def fun(x):
melted = pd.melt(x.reset_index(), id_vars=['name', 'year'], value_vars=['teamA', 'teamB'], var_name='var_name',
value_name='team')
toRemove = melted.team.mode().iloc[0]
for col in ["teamA", "teamB"]:
x[col] = x[col].replace(toRemove,'something')
return x
df = df.groupby(["name", "year"]).apply(fun)
因此,我融化了我的数据帧,并在从两列中移除该值之后找到最频繁的值。
谢谢@rpanai!每个答案都很有帮助,但你的答案是最有用的 所以,我的问题显然不完整。如果我必须按两列进行分组怎么办?如果有两个以上的重复项,如下面的示例所示,该怎么办
name teamA teamB foo a b foo b c foo b c bar a e bar a d
我只想删除b值,因为它们显示在每一行中。我可以这样做,比如删除最频繁的值或类似的东西,但我的主要问题是按两列进行分组。因此,我的问题显然不完整。如果我必须按两列进行分组怎么办?如果有两个以上的重复项,比如下面的例子(我也会编辑我的主要问题,这样你们就可以很好地看到它了),会怎么样name teamA teamB foo a b foo b c foo b c bar a e bar a d
我只想删除b值,因为它们显示在每一行中。我可以这样做,比如删除最频繁的值或类似的东西,但我的主要问题是通过两列进行分组。你的答案非常有用,但我的问题不完整。请看我在主要问题中编辑的表格。
(df[['teamA', 'teamB']].groupby(df.name, sort=False)
.apply(lambda x: x.stack().drop_duplicates(keep=False))
.unstack().fillna('').reset_index('name'))
Out[93]:
name teamA teamB
0 foo a
1 foo c
2 foo d
3 bar e
4 bar d
name teamA teamB year
foo a b 1
foo b c 1
foo c b 1
bar a e 2
bar a d 2
foo a h 2
foo h c 2
foo h b 2
...
def fun(x):
melted = pd.melt(x.reset_index(), id_vars=['name', 'year'], value_vars=['teamA', 'teamB'], var_name='var_name',
value_name='team')
toRemove = melted.team.mode().iloc[0]
for col in ["teamA", "teamB"]:
x[col] = x[col].replace(toRemove,'something')
return x
df = df.groupby(["name", "year"]).apply(fun)