【问题标题】:Pandas drop before first valid index and after last valid index for each column of a dataframePandas 在数据帧的每一列的第一个有效索引之前和最后一个有效索引之后下降
【发布时间】:2018-12-01 16:16:42
【问题描述】:

我有一个这样的数据框:

df = pd.DataFrame({'timestamp':pd.date_range('2018-01-01', '2018-01-02', freq='2h', closed='right'),'col1':[np.nan, np.nan, np.nan, 1,2,3,4,5,6,7,8,np.nan], 'col2':[np.nan, np.nan, 0, 1,2,3,4,5,np.nan,np.nan,np.nan,np.nan], 'col3':[np.nan, -1, 0, 1,2,3,4,5,6,7,8,9], 'col4':[-2, -1, 0, 1,2,3,4,np.nan,np.nan,np.nan,np.nan,np.nan]
              })[['timestamp', 'col1', 'col2', 'col3', 'col4']]

看起来像这样:

             timestamp  col1  col2  col3  col4
0  2018-01-01 02:00:00   NaN   NaN   NaN  -2.0
1  2018-01-01 04:00:00   NaN   NaN  -1.0  -1.0
2  2018-01-01 06:00:00   NaN   0.0   NaN   0.0
3  2018-01-01 08:00:00   1.0   1.0   1.0   1.0
4  2018-01-01 10:00:00   2.0   NaN   2.0   2.0
5  2018-01-01 12:00:00   3.0   3.0   NaN   3.0
6  2018-01-01 14:00:00   NaN   4.0   4.0   4.0
7  2018-01-01 16:00:00   5.0   NaN   5.0   NaN
8  2018-01-01 18:00:00   6.0   NaN   6.0   NaN
9  2018-01-01 20:00:00   7.0   NaN   7.0   NaN
10 2018-01-01 22:00:00   8.0   NaN   8.0   NaN
11 2018-01-02 00:00:00   NaN   NaN   9.0   NaN

现在,我想在第一个有效索引之前和最后一个有效索引之后找到一种有效且 Pythonic 的切断方式(对于每一列!不计算时间戳)。在这个例子中,我有 4 列,但实际上我有更多,大约 600 列。我正在寻找一种对第一个有效索引之前的所有 NaN 值和最后一个有效索引之后的所有 NaN 值进行切割的方法。

我猜一种方法是循环。但是有更好的方法吗?这种方式必须是有效的。我尝试使用熔化“取消旋转”数据框,但这并没有帮助。

很明显的一点是,每列在切割后会有不同的行数。因此,我希望结果是具有时间戳和相关列的数据帧列表(每列一个)。例如:

             timestamp  col1   
3  2018-01-01 08:00:00   1.0  
4  2018-01-01 10:00:00   2.0   
5  2018-01-01 12:00:00   3.0   
6  2018-01-01 14:00:00   NaN   
7  2018-01-01 16:00:00   5.0   
8  2018-01-01 18:00:00   6.0   
9  2018-01-01 20:00:00   7.0   
10 2018-01-01 22:00:00   8.0    

我的尝试

我试过这样:

final = []
columns = [c for c in df if c !='timestamp']
for col in columns:
    first = df.loc[:, col].first_valid_index()
    last = df.loc[:, col].last_valid_index()
    final.append(df.loc[:, ['timestamp', col]].iloc[first:last+1, :])

【问题讨论】:

  • 我的一个想法是使用 groupby,但尝试了一个小时后我放弃了..
  • 您当前的方法似乎工作正常。你主要关心什么?效率,可维护性,两者兼而有之?
  • 效率为主,这是一个很小的例子。我的数据框很大,这种方法的问题是使用for 语句。但是对于一个大型数据框,这似乎崩溃了。我希望 groupby 可以更快地解决这个问题

标签: python pandas


【解决方案1】:

一个想法是在将索引设置为timestamp 后使用列表或字典理解。您应该使用您的数据进行测试,看看这是否能解决您的性能问题。如果您的限制是记忆力,这不太可能有帮助。

df = df.set_index('timestamp')

final = {col: df[col].loc[df[col].first_valid_index(): df[col].last_valid_index()] \
         for col in df}

print(final)

{'col1': timestamp
2018-01-01 08:00:00    1.0
2018-01-01 10:00:00    2.0
2018-01-01 12:00:00    3.0
2018-01-01 14:00:00    4.0
2018-01-01 16:00:00    5.0
2018-01-01 18:00:00    6.0
2018-01-01 20:00:00    7.0
2018-01-01 22:00:00    8.0
Name: col1, dtype: float64,
...
'col4': timestamp
2018-01-01 02:00:00   -2.0
2018-01-01 04:00:00   -1.0
2018-01-01 06:00:00    0.0
2018-01-01 08:00:00    1.0
2018-01-01 10:00:00    2.0
2018-01-01 12:00:00    3.0
2018-01-01 14:00:00    4.0
Name: col4, dtype: float64}

【讨论】:

    【解决方案2】:

    您可以利用函数式编程的强大功能并将函数应用于每一列。这可能会加快速度。此外,当您的 timestamps 看起来已排序时,您可以将它们用作 Datarame 的索引。

    df.set_index('timestamp', inplace=True)
    
    final = []
    def func(col):
        first = col.first_valid_index()
        last = col.last_valid_index()
        final.append(col.loc[first:last])
        return
    
    df.apply(func)
    

    此外,您可以将所有内容压缩在一个衬垫中:

    final = []
    df.apply(lambda col: final.append(col.loc[col.first_valid_index() : col.last_valid_index()]))
    

    【讨论】:

      【解决方案3】:

      我的方法是找到每列的 NaN 的累积和及其倒数,并过滤那些大于 0 的条目。然后我做一个dict理解来为每一列返回一个数据框(如果你喜欢的话,你可以将它更改为一个列表)。

      对于你的例子,我们有

      cols = [c for c in df.columns if c!='timestamp']
      
      result_dict = {c: df[(df[c].notnull().cumsum() > 0) &
                           (df.ix[::-1,c].notnull().cumsum()[::-1] > 0)][['timestamp', c]]
                     for c in cols}
      

      【讨论】:

        猜你喜欢
        • 2018-11-24
        • 2021-07-18
        • 1970-01-01
        • 2023-01-19
        • 2022-01-09
        • 2020-07-26
        • 2018-01-01
        • 2018-02-15
        • 2013-02-14
        相关资源
        最近更新 更多