pandas 通过在具有相同形状的另一个DataFrame上应用2D遮罩来创建新的DataFrame

wgx48brx  于 2023-04-28  发布在  其他
关注(0)|答案(4)|浏览(155)

是否有一种快速简单的方法来创建一个新的 Dataframe ,基于一个掩码的 Dataframe 和一个具有以下值的 Dataframe :

df_1 = pd.DataFrame(data = [[False, True],[True, False],[False, True], [False, False]] )

    0       1   
0   False   True
1   True    False
2   False   True
3   False   False

df_2 = pd.DataFrame(data = [[1, 2],[3, 4],[5, 6], [7, 8]] )

    0   1
0   1   2
1   3   4
2   5   6
3   7   8

我想要的结果是一个新的dataframe,它只包含掩码为TRUE的值:

0   1
0   3   2
1   NaN 6
pexxcrt2

pexxcrt21#

所以看起来这个问题中有两个请求:
1.屏蔽我们不需要的值,以及
1.折叠行以使结果密集(除最后一行外,行之间没有NaN)
要执行第一个,使用df.where。要执行第二个,我们需要先执行stack以消除NaNs,然后重置每列的索引,以便在unstack输出时可以将非空值重新分配给新的密集行。

(df_2.where(df_1)
     .stack()
     .groupby(level=1)
     .apply(lambda d: d.reset_index(drop=True))
     .unstack(0))

     0    1
0  3.0  2.0
1  NaN  6.0

如果性能很重要,这里有另一个不涉及(un)stacking的尝试:

m = df_2.where(df_1)
pd.DataFrame([m[c].to_numpy()[m[c].notna()] for c in m.columns]).T

     0    1
0  3.0  2.0
1  NaN  6.0
nxowjjhe

nxowjjhe2#

有一个函数可以在框架上应用掩码,但我相信它不适用于你的情况。如果我想像你发布的那样得到输出,我会使用concat和for循环。类似于这样:

df_1 = pd.DataFrame(data = [[False, True],[True, False],[False, True], [False, False]] )
df_2 = pd.DataFrame(data = [[1, 2],[3, 4],[5, 6], [7, 8]] )
temp_arr = []
for col in df_2.columns:
    mask = df_1[col].values
    temp_df = df_2.loc[mask, col].reset_index(drop=True)
    temp_arr.append(temp_df)
print(temp_arr)
pd.concat(temp_arr,axis=1, ignore_index=True)

有了这个你应该得到你想要的。

zbsbpyhn

zbsbpyhn3#

我注意到你在做一些让我很困惑的事情。我无法理解你在最后一个代码片段中寻找的结果,因为它看起来像是任意合并了一些行。尽管如此,也许这会有所帮助:

# given df_1 and df_2
df3 = df_1 * df_2 # to only keep the `True` values
df3.loc[(df3!=0).any(axis=1)] # to discard rows that are completely zeros

你应该得到这样的东西:

0  1
0  0  2
1  3  0
2  0  6
ibps3vxo

ibps3vxo4#

可以使用dataframe的where子句,
使用布尔索引根据df_1掩码过滤df_2,并删除所有值均为NaN的行
result = df_2.where(df_1)
result = result.dropna(how='all')
print (result)
给予

0    1
0  NaN  2.0
1  3.0  NaN
2  NaN  6.0

相关问题