使用 np.where 创建元素数量相同但内容不同的列表

问题描述 投票:0回答:2

我有一个 pandas 数据框,其中的值有时会变为 NA。我想用与另一列长度相同的字符串列表填充此列:

import pandas as pd
import numpy as np

df = pd.DataFrame({"a": ["one", "two"],
                   "b": ["three", "four"],
                   "c": [[1, 2], [3, 4]],
                   "d": [[5, 6], np.nan]})
a b c d
一个 [1, 2] [5, 6]
两个 [3, 4] NaN

我希望这成为

a b c d
一个 [1, 2] [5, 6]
两个 [3, 4] [无值,无值]
df["d"] = np.where(df.d.isna(),
                   [np.nan for element in df.c],
                   df.d) # this doesn't work

我试过了

df["d"] = np.where(df.d.isna(),
                   ['no_value' for element in df.c],
                   df.d)

df["d"] = np.where(df.d.isna(),
                   ['no_value'] * len(df.c),
                   df.d)

但是两者都不起作用。有人有想法吗?

python pandas numpy
2个回答
1
投票

一个可能的解决方案是使用

np.where

df.assign(d = np.where(
    df['d'].isna(), 
    pd.Series([['no_value'] * len(lst) for lst in df['c']]), 
    df['d']))

另一种可能的解决方案,它使用:

  • apply
    df
    上,使用 lambda 函数迭代每一行,检查列
    d
    中的值是否为
    NaN

  • 如果满足条件,该函数会生成一个新列表,其中填充字符串

    'no_value'
    ,并重复以匹配列
    c
    中列表的长度。

  • 如果

    x['d']
    不满足这些条件,则保留
    x['d']
    中的原始值。

df['d'] = df.apply(
    lambda x: ['no_value'] * len(x['c']) 
    if (x['d'] is np.nan) else x['d'], axis=1)

输出:

     a      b       c                     d
0  one  three  [1, 2]                [5, 6]
1  two   four  [3, 4]  [no_value, no_value]

0
投票

要使用

where
,我们必须构造一个正确的
nan
包含数组,类似于
df.d
,具有对象数据类型列表。

In [317]: df1=df.copy();df1
Out[317]: 
     a      b       c       d
0  one  three  [1, 2]  [5, 6]
1  two   four  [3, 4]     NaN

要完全控制,请从

empty
对象数据类型数组开始,然后填充它。

In [318]: x=np.empty(len(df.c), object)    
In [319]: x[:] = [[np.nan]*len(element) for element in df.c]; x
Out[319]: array([list([nan, nan]), list([nan, nan])], dtype=object)

如果

df.c
列表的长度不同,则不需要这两个步骤。 现在
where
可以使用
[False, True]
条件在 2 个对象数据类型数组的元素之间进行选择。

In [320]: df1.d = np.where(df.d.isna(), x, df.d)

In [321]: df1
Out[321]: 
     a      b       c           d
0  one  three  [1, 2]      [5, 6]
1  two   four  [3, 4]  [nan, nan]


In [326]: x = [[np.nan]*len(element) for element in df.c]; x
Out[326]: [[nan, nan], [nan, nan]]

不行,因为它是 (2,2) 形状,并且

where
在使用其他项((2,) 系列)“广播”该形状时会遇到问题。

或者你可以将

x
初始化为

x = df.c.copy()
© www.soinside.com 2019 - 2024. All rights reserved.