筛选列表中与每行的条件匹配的第一个元素

2024-04-30 05:55:33 发布

您现在位置:Python中文网/ 问答频道 /正文

问题/问题:我想创建另一个列,其中包含符合条件(与“nan”不同)的列表中的第一列(多个)/或值。你知道吗

我正在研究一个数据帧,它有多个列作为标志,每个列都是不同类型的标志。它看起来是这样的:

         id_number  createdat  ... flag_3.3.3.2.1 flag_3.3.3.2.2 flag_3.3.3.3.1
1             718v 2019-08-14  ...            nan      3.3.3.2.2      3.3.3.3.1
2             566m 2019-07-10  ...            nan            nan            nan
3             636p 2019-06-12  ...      3.3.3.2.1            nan      3.3.3.3.1
4             630r 2019-06-30  ...            nan            nan            nan
26815         066p 2019-08-24  ...      3.3.3.2.1      3.3.3.2.2      3.3.3.3.1
26816         769b 2019-08-10  ...            nan            nan            nan

我已经创建了一个列,它生成了一个包含“flag\的列的所有值的列表:

payday_cols = [col for col in df if col.startswith('flag_')]
df['flagging'] = df[payday_cols].values.tolist()
print(df)
         id_number  ... flag_3.3.3.3.1                                           flagging
1             718v  ...            nan  [nan, nan, nan, nan, nan, nan, nan, nan, nan, ...
2             566m  ...            nan  [nan, nan, nan, nan, nan, nan, nan, nan, nan, ...
3             636p  ...            nan  [nan, nan, 2.2, nan, nan, nan, nan, nan, nan, ...
4             630r  ...            nan  [nan, nan, nan, 3.1, nan, nan, nan, nan, 3.3.2...                                          ...
26815         066p  ...      3.3.3.3.1  [nan, nan, nan, nan, 3.2, nan, nan, nan, nan, ...
26816         769b  ...            nan  [1, nan, nan, nan, nan, nan, nan, nan, 3.3.2.1...

我缺少的是一种创建最后一列的方法,该列包含与nan不同的列表的第一个值,如果没有与nan不同的值,则为nan。输出如下:

         id_number  ... flag_3.3.3.3.1                                           flagging      flag
1             718v  ...            nan  [nan, nan, nan, nan, nan, nan, nan, nan, nan, ...       nan
2             566m  ...            nan  [nan, nan, nan, nan, nan, nan, nan, nan, nan, ...       nan
3             636p  ...            nan  [nan, nan, 2.2, nan, nan, nan, nan, nan, nan, ...       2.2
4             630r  ...            nan  [nan, nan, nan, 3.1, nan, nan, nan, nan, 3.3.2...       3.1
26815         066p  ...      3.3.3.3.1  [nan, nan, nan, nan, 3.2, nan, nan, nan, nan, ...       3.2
26816         769b  ...            nan  [1, nan, nan, nan, nan, nan, nan, nan, 3.3.2.1...   3.3.2.1

非常感谢,如果你需要我生成类似这些的值,这样你就可以重新创建这个案例,我会用它编辑这个帖子。你知道吗


Tags: 数据id类型numberdf列表标志col
3条回答

我的解决方案是:

  • 将包含列表的列转换为数据帧(应用 你知道吗pd系列到每个元素)。你知道吗
  • 基于第一个有效索引将函数应用于每一行。你知道吗

所以我们假设df是:

df = pd.DataFrame({ "flagging": [
    [np.nan, np.nan, np.nan, np.nan], [np.nan, 2.2, np.nan, 0.2],
    [np.nan, 1.1, np.nan, np.nan], [np.nan, np.nan, np.nan, 3.1]]})

定义以下函数:

def func(x):
    ind = x.first_valid_index()
    return None if ind is None else x[ind]

然后应用它:

df.flagging.apply(pd.Series).apply(func, axis=1)

方法1:

试试bfill.iloc

df[payday_cols].bfill(1).iloc[:,0]

Out[92]:
1        3.3.3.2.2
2              NaN
3        3.3.3.2.1
4              NaN
26815    3.3.3.2.1
26816          NaN
Name: flag_3.3.3.2.1, dtype: object

方法2:

另一种解决方案是在notna上使用numpy argmax,并将结果传递给lookup

m = df[payday_cols].notna().values.argmax(1)
df[payday_cols].lookup(df.index, np.array(payday_cols)[m])

Out[145]: array(['3.3.3.2.2', nan, '3.3.3.2.1', nan, '3.3.3.2.1', nan], dtype=object)

注:输出基于此示例

In [83]: df

Out[83]:
      id_number   createdat flag_3.3.3.2.1 flag_3.3.3.2.2 flag_3.3.3.3.1  
1          718v  2019-08-14            NaN      3.3.3.2.2      3.3.3.3.1
2          566m  2019-07-10            NaN            NaN            NaN
3          636p  2019-06-12      3.3.3.2.1            NaN      3.3.3.3.1
4          630r  2019-06-30            NaN            NaN            NaN
26815      066p  2019-08-24      3.3.3.2.1      3.3.3.2.2      3.3.3.3.1
26816      769b  2019-08-10            NaN            NaN            NaN

这应该管用。你知道吗

df = pd.DataFrame({
    "flagging": [[np.nan, np.nan, np.nan, np.nan], [np.nan, 2.2, np.nan, 0.2], [np.nan, 1.1, np.nan, np.nan], [np.nan, np.nan, np.nan, 3.1]]
})

def get_element(xs):
    xs = [x for x in xs if not pd.isna(x)]
    if xs:
        return xs[0]
    return np.nan

df["flagging"].apply(get_element)

输出:

0    NaN
1    2.2
2    1.1
3    3.1

相关问题 更多 >