Python 如何用不同于Pandas数据帧中的孤立NaN的值替换重复NaN

Python 如何用不同于Pandas数据帧中的孤立NaN的值替换重复NaN,python,pandas,dataframe,nan,repeat,Python,Pandas,Dataframe,Nan,Repeat,我在一个数据帧中安排了几个时间序列,如下所示: category value time_idx 0 810 0.118794 0 1 830 0.552947 0 2 1120 0.133193 0 3 1370 0.840183 0 4 810 0.129385 1 ... ... ... ... 6095 1370 0.157391 1523 6096 810 0.141377

我在一个数据帧中安排了几个时间序列,如下所示:


   category value   time_idx
0   810     0.118794    0
1   830     0.552947    0
2   1120    0.133193    0
3   1370    0.840183    0
4   810     0.129385    1
... ... ... ...
6095 1370   0.157391    1523
6096 810    0.141377    1524
6097 830    0.212254    1524
6098 1120   0.069970    1524
6099 1370   0.134947    1524
有些值是NaN。我想用0替换任何没有重复的NaN值,因为我假设当时该类别的值为0。但是,任何时候,如果每个类别在同一时间有一个值NaN(即,在同一时间_idx),那么我想用-1替换每个值

在熊猫身上,仅仅用一个值来替换NaN当然是微不足道的,但在给定时间专门替换每个类别的NaN所增加的复杂性让我感到困惑。我知道我可以循环使用时间索引,但我的实际数据集将有900多个类别,因此我想找到一种更有效的方法

我能想到的唯一一件事就是列表理解,我认为它甚至不一定比显式循环更有效,而且我也不能想出一个工作正常的循环

我知道我可以这样替换所有的NAN:

data[“value”]=data[“value”].替换(np.nan,0)

但我不确定如何在我的例子中实现这一点,我只想用0替换长NaN。这是我目前的循环:

num_channels = data["category"].nunique()
nan_vals = data[lambda x: np.isnan(x.value)]
nan_times = nan_vals["time_idx"]

for time in nan_times:
        if nan_vals[lambda x: x.time_idx == time]["category"].nunique() < num_channels:
            # Set 0 for every channel that has nan at time t
            index = nan_vals[lambda x: x.time_idx == time].index

            data.loc[index, ["value"]] =  data.loc[index, "value"].replace(np.nan, 0)

        else:

            index = nan_vals[lambda x: x.time_idx == time].index
            data.loc[index, ["value"]] = data[lambda x: x.time_idx == time]["value"].replace(np.nan, -1)
我希望此输出:

    category    value   time_idx
0   810        -1.000000    0
1   830        -1.000000    0
2   1120       -1.000000    0
3   1370       -1.000000    0
4   810         0.129385    1
5   830         0.000000    1
6   1120        0.144378    1
7   1370        0.000000    1
8   810         0.124334    2
9   830         0.487274    2
10  1120        0.119153    2
11  1370        0.871687    2

在本例中,在time=0时,每个类别的值都是NaN,因此它们将替换为-1。在time=1时,存在非NaN值,因此存在的任何NaN值(类别830和1370)都将替换为0。

您可以使用
groupby
找到那些
time\u idx
,其中所有条目都是NaN,然后使用
group.isna().all()
。您可以使用该遮罩用
-1
填充NAN

然后使用
fillna
0
填充到所有其他NAN中

all_nas = df.groupby("time_idx").value.apply(lambda group: group.isna().all())
df = df.set_index("time_idx")
df.loc[all_nas, "value"] = -1
df = df.reset_index().fillna(0)
print(df)

#     time_idx  category     value
# 0          0       810 -1.000000
# 1          0       830 -1.000000
# 2          0      1120 -1.000000
# 3          0      1370 -1.000000
# 4          1       810  0.129385
# 5          1       830  0.000000
# 6          1      1120  0.144378
# 7          1      1370  0.000000
# 8          2       810  0.124334
# 9          2       830  0.487274
# 10         2      1120  0.119153
# 11         2      1370  0.871687

您可以按
time\u idx
分组,并在组上迭代。 然后在每组中,计算
value
列中
NaN
值的数量。 根据NAN的数量,可以更新


import pandas as pd

df = pd.DataFrame(
    {
        'category': [810, 830, 1120, 810, 830, 1120, 810, 830, 1120],
        'value': [None, None, None, 1, 2, None, None, None, 4],
        'time_idx': [0, 0, 0, 1, 1, 1, 2, 2, 2],
    }
)

print(df, end='\n\n')


for name, group in df.copy().groupby('time_idx'):
    num_nans = group['value'].isnull().sum()
    mask = (df['time_idx'] == name) & df['value'].isna()
    if num_nans == len(group):
        df.loc[mask, 'value'] = -1
    else:
        df.loc[mask, 'value'] = 0

print(df)

输出

   category  value  time_idx
0       810    NaN         0
1       830    NaN         0
2      1120    NaN         0
3       810    1.0         1
4       830    2.0         1
5      1120    NaN         1
6       810    NaN         2
7       830    NaN         2
8      1120    4.0         2

   category  value  time_idx
0       810   -1.0         0
1       830   -1.0         0
2      1120   -1.0         0
3       810    1.0         1
4       830    2.0         1
5      1120    0.0         1
6       810    0.0         2
7       830    0.0         2
8      1120    4.0         2

嗨,Ryan,你试过我们可以调查的东西吗?嗨,Anwarvic,谢谢你的回答。我能够通过每次循环成功地实现它,但正如我所提到的,我想更有效地实现它。我将在我的问题后面附上我的想法的更多细节。@RyanDempsey您能展示输入数据帧的示例和预期的输出吗?
   category  value  time_idx
0       810    NaN         0
1       830    NaN         0
2      1120    NaN         0
3       810    1.0         1
4       830    2.0         1
5      1120    NaN         1
6       810    NaN         2
7       830    NaN         2
8      1120    4.0         2

   category  value  time_idx
0       810   -1.0         0
1       830   -1.0         0
2      1120   -1.0         0
3       810    1.0         1
4       830    2.0         1
5      1120    0.0         1
6       810    0.0         2
7       830    0.0         2
8      1120    4.0         2