【问题标题】:Fill all values in a group with the first non-null value in that group用该组中的第一个非空值填充组中的所有值
【发布时间】:2018-11-30 03:56:12
【问题描述】:

以下是我拥有的 pandas 数据框:

cluster Value
1         A
1        NaN
1        NaN
1        NaN
1        NaN
2        NaN
2        NaN
2         B
2        NaN
3        NaN
3        NaN
3         C
3        NaN
4        NaN
4         S
4        NaN
5        NaN
5         A
5        NaN
5        NaN

如果我们查看数据,集群 1 的一行具有值“A”,并且仍然是 NA 值。我想为集群 1 的所有行填充“A”值。对于所有集群也是如此。基于集群的值之一,我想填充集群的剩余行。输出应该是,

cluster Value
1         A
1         A
1         A
1         A
1         A
2         B
2         B
2         B
2         B
3         C
3         C
3         C
3         C
4         S
4         S
4         S
5         A
5         A
5         A
5         A

我是 python 新手,不知道如何继续。有人可以帮忙吗?

【问题讨论】:

  • 什么是print(df['Value'].dtype)
  • @jedwards 对象(字符串)
  • 重新打开,因为我认为副本与此问题无关。
  • 我认为df['Value'] = df.groupby('cluster').Value.transform('first') 是去这里的方式。

标签: python pandas dataframe nan


【解决方案1】:

groupby + bfillffill

df = df.groupby('cluster').bfill().ffill()
df

    cluster Value
0         1     A
1         1     A
2         1     A
3         1     A
4         1     A
5         2     B
6         2     B
7         2     B
8         2     B
9         3     B
10        3     B
11        3     C
12        3     C
13        4     S
14        4     S
15        4     S
16        5     A
17        5     A
18        5     A
19        5     A

或者,

groupby + transformfirst

df['Value'] = df.groupby('cluster').Value.transform('first')
df

    cluster Value
0         1     A
1         1     A
2         1     A
3         1     A
4         1     A
5         2     B
6         2     B
7         2     B
8         2     B
9         3     B
10        3     B
11        3     C
12        3     C
13        4     S
14        4     S
15        4     S
16        5     A
17        5     A
18        5     A
19        5     A

【讨论】:

    【解决方案2】:

    编辑

    以下似乎更好:

    nan_map = df.dropna().set_index('cluster').to_dict()['Value']
    df['Value'] = df['cluster'].map(nan_map)
    
    print(df)
    

    原创

    我想不出比遍历所有行更好的方法,但可能存在一种方法。首先,我构建了您的 DataFrame:

    import pandas as pd
    import math
    
    # Build your DataFrame
    df = pd.DataFrame.from_items([
        ('cluster', [1,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,5,5,5,5]),
        ('Value', [float('nan') for _ in range(20)]),
    ])
    df['Value'] = df['Value'].astype(object)
    df.at[ 0,'Value'] = 'A'
    df.at[ 7,'Value'] = 'B'
    df.at[11,'Value'] = 'C'
    df.at[14,'Value'] = 'S'
    df.at[17,'Value'] = 'A'
    

    现在这是一种方法,首先创建一个nan_map dict,然后按照dict 中的指定设置Value 中的值。

    # Create a dict to map clusters to unique values
    nan_map = df.dropna().set_index('cluster').to_dict()['Value']
    # nan_map: {1: 'A', 2: 'B', 3: 'C', 4: 'S', 5: 'A'}
    
    # Apply
    for i, row in df.iterrows():
        df.at[i,'Value'] = nan_map[row['cluster']]
    
    print(df)
    

    输出:

    集群价值 0 1 安 1 1 安 2 1 安 3 1 安 4 1 安 5 2 乙 6 2 乙 7 2 乙 8 2 乙 9 3℃ 10 3℃ 11 3℃ 12 3℃ 13 4 秒 14 4 秒 15 4 秒 16 5 安 17 5 安 18 5 安 19 5 安

    注意:这会根据集群设置 all 值,并且不检查 NaN 值。您可能想尝试以下方法:

    # Apply
    for i, row in df.iterrows():
        if isinstance(df.at[i,'Value'], float) and math.isnan(df.at[i,'Value']):
            df.at[i,'Value'] = nan_map[row['cluster']]
    

    看看哪个更有效率(我猜是前者,没有检查)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-09-17
      • 2021-09-19
      • 1970-01-01
      • 2021-10-15
      • 1970-01-01
      • 2020-03-21
      相关资源
      最近更新 更多