我想根据特定条件从DataFrame中选择列。我知道它可以通过循环完成,但我的df非常大,因此效率至关重要。列选择的条件是仅具有非纳米条目或仅具有nans的序列,其后仅具有非纳米条目的序列。
这是一个例子。请考虑以下DataFrame:
pd.DataFrame([[1, np.nan, 2, np.nan], [2, np.nan, 5, np.nan], [4, 8, np.nan, 1], [3, 2, np.nan, 2], [3, 2, 5, np.nan]])
0 1 2 3
0 1 NaN 2.0 NaN
1 2 NaN 5.0 NaN
2 4 8.0 NaN 1.0
3 3 2.0 NaN 2.0
4 3 2.0 5.0 NaN
从中,我想只选择第0列和第1列。有关如何在不循环的情况下有效地执行此操作的任何建议吗?
答案 0 :(得分:2)
<强> 逻辑 强>
cnull = df.isnull().sum()
fvald = df.apply(pd.Series.first_valid_index)
cols = df.index[cnull] == fvald
df.loc[:, cols]
编辑速度改进
旧答案
def pir1(df):
cnull = df.isnull().sum()
fvald = df.apply(pd.Series.first_valid_index)
cols = df.index[cnull] == fvald
return df.loc[:, cols]
使用相同的逻辑更快地回答
def pir2(df):
nulls = np.isnan(df.values)
null_count = nulls.sum(0)
first_valid = nulls.argmin(0)
null_on_top = null_count == first_valid
filtered_data = df.values[:, null_on_top]
filtered_columns = df.columns.values[null_on_top]
return pd.DataFrame(filtered_data, df.index, filtered_columns)
答案 1 :(得分:1)
如下所示,请考虑DF
Nans
,其中Nans
位于不同的位置:
1。 双方mask = np.where(np.isnan(df), 0, 1)
在场 :
通过将所有nans替换为0和有限值替换为1来创建掩码:
criteria = pd.DataFrame(mask, columns=df.columns).diff(1).abs().sum().lt(2)
在每列中获取相应的元素差异。接下来,取其值的模数。这里的逻辑是,每当每列中有三个唯一值时,则丢弃该列(即→-1,1,0),因为这种情况的序列会中断。
想法是获取总和并在总和导致小于2的值的任何地方创建子集。(在采用mod之后,我们得到1,1,0)。因此,对于极端情况,我们得到总和为2,那些列肯定是不相交的,必须丢弃。
DF
最后转置Nans
并使用此条件并重新转置以获得所需的结果,其中一部分只有df.loc[:, criteria]
而另一部分只有有限值。
Nans
<强> 2。 mask = np.where(np.isnan(df), 0, 1)
criteria = pd.DataFrame(mask, columns=df.columns).diff(1).ne(-1).any()
df.loc[:, criteria]
位于顶部:
body{ width:100%; height:100%; }
div1{ width:100%; height:40%; }
div2{ width:100%; height:30%; }
div3{ width:100%; height:30%; }