我有一个以日期为索引的Pandas DataFrame
。有许多列,但是很多列只在时间序列的一部分填充了值。我想找到第一个和最后一个非NaN
值的位置,以便我可以提取日期并查看特定列的时间序列有多长。
请问有人能指点我如何实现这样的操作吗?
@behzad.nouri的解决方案完美地返回了第一个和最后一个非NaN值
,分别使用Series.first_valid_index和Series.last_valid_index函数。
df
中检查更多列,可以迭代您的 df。例如:for col_name, data in df.items(): print("First valid index for column {} is at {}".format(col_name, data.first_valid_index()))
- Jasondf.apply(Series.first_valid_index)
来代替对 DataFrame 列的迭代。 - Peque这里有一些有用的例子。
s = pd.Series([np.NaN, 1, np.NaN, 3, np.NaN], index=list('abcde'))
s
a NaN
b 1.0
c NaN
d 3.0
e NaN
dtype: float64
# first valid index
s.first_valid_index()
# 'b'
# first valid position
s.index.get_loc(s.first_valid_index())
# 1
# last valid index
s.last_valid_index()
# 'd'
# last valid position
s.index.get_loc(s.last_valid_index())
# 3
使用notna
和idxmax
的替代方案:
# first valid index
s.notna().idxmax()
# 'b'
# last valid index
s.notna()[::-1].idxmax()
# 'd'
df = pd.DataFrame({
'A': [np.NaN, 1, np.NaN, 3, np.NaN],
'B': [1, np.NaN, np.NaN, np.NaN, np.NaN]
})
df
A B
0 NaN 1.0
1 1.0 NaN
2 NaN NaN
3 3.0 NaN
4 NaN NaN
(first|last)_valid_index
在数据框(DataFrames)中未定义,但您可以使用apply
函数在每一列上应用它们。
# first valid index for each column
df.apply(pd.Series.first_valid_index)
A 1
B 0
dtype: int64
# last valid index for each column
df.apply(pd.Series.last_valid_index)
A 3
B 0
dtype: int64
和之前一样,您也可以使用notna
和idxmax
。这是稍微更自然的语法。
# first valid index
df.notna().idxmax()
A 1
B 0
dtype: int64
# last valid index
df.notna()[::-1].idxmax()
A 3
B 0
dtype: int64
idxmax()
的问题在于,对于一个完全由 NaN
组成的列,它会返回 0
。在这种情况下,我希望返回 NaN
,因此我更愿意始终使用 .apply(Series.first_valid_index)
。 - Pequedf.apply(pd.Series.first_valid_index).max()
查找第一个没有 NaN 的索引。 - pseudoabdul这是一个基于behzad.nouri的代码和cs95之前的回答的方便函数。任何错误或误解都是我的责任。
import pandas as pd
import numpy as np
df = pd.DataFrame([["2022-01-01", np.nan, np.nan, 1], ["2022-01-02", 2, np.nan, 2], ["2022-01-03", 3, 3, 3], ["2022-01-04", 4, 4, 4], ["2022-01-05", np.nan, 5, 5]], columns=['date', 'A', 'B', 'C'])
df['date'] = pd.to_datetime(df['date'])
df
# date A B C
#0 2022-01-01 NaN NaN 1.0
#1 2022-01-02 2.0 NaN 2.0
#2 2022-01-03 3.0 3.0 3.0
#3 2022-01-04 4.0 4.0 4.0
#4 2022-01-05 NaN 5.0 5.0
# filter data to minimum/maximum common available dates
def get_date_range(df, cols):
"""return a tuple of the earliest and latest valid data for all columns in the list"""
a,b = df[cols].apply(pd.Series.first_valid_index).max(), df[cols].apply(pd.Series.last_valid_index).min()
return (df.loc[a, 'date'], df.loc[b, 'date'])
a,b = get_date_range(df, cols=['A', 'B'])
a
#Timestamp('2022-01-03 00:00:00')
b
#Timestamp('2022-01-04 00:00:00')
df.loc[(df.date >= a) & (df.date <= b)]
# date A B C
#2 2022-01-03 3.0 3.0 3
#3 2022-01-04 4.0 4.0 4
first_valid_index
和last_valid_index
是Pandas 库中的两个函数,用于获取 Series 对象中第一个和最后一个非空值的索引位置。使用这两个函数可以方便地找到数据集中的有效数据范围。 - behzad.nouri