通过 prod() 函数重新采样 datetimeindex 将 NaN 更改为 1
resample datetimeindex via prod() function changes NaN to 1
我正在处理一个相当大的数据集。在将 resample 命令与转换方法“prod”(乘法)结合使用后,我意识到我的 NaN 值已更改为 1,这不是我想要的。举个例子:
# build random dataframe with one column containing NaN
import pandas as pd
import numpy as np
index = pd.date_range('1/1/2000', periods=7, freq='d')
df = pd.DataFrame(index = index, columns = ["Score 1", "Score 2", "Score 3"])
df["Score 1"] = np.random.randint(1,20,size=7)
df["Score 2"] = np.random.randint(1,20,size=7)
df["Score 3"] = [1, 2, 3, np.NaN, np.NaN, np.NaN, np.NaN]
print(df)
Score 1 Score 2 Score 3
2000-01-01 6 7 1.0
2000-01-02 2 15 2.0
2000-01-03 8 19 3.0
2000-01-04 14 19 NaN
2000-01-05 17 8 NaN
2000-01-06 15 6 NaN
2000-01-07 12 18 NaN
现在假设我想使用“prod”转换方法将我的 Dataframe 从每日频率重新采样为 3 天频率。我这样做:
df.resample("3d").agg("prod")
print(df)
Score 1 Score 2 Score 3
2000-01-01 96 1995 6.0
2000-01-04 3570 2052 1.0
2000-01-07 12 18 1.0
看着“Score 3”这一列,我的NaN值突然变成了1,这让我很惊讶。这意味着当将 NaN 相互相乘时,我会得到 =1。有人知道为什么 NaN 的乘法正好等于 1 吗?我可以做些什么来保持 NaN 值以防它与自身相乘?
在此先致谢,非常感谢任何帮助
pandas.DataFrame.prod
函数 (docs) 默认将 NaN
设置为 1:
pd.Series([np.NaN, np.NaN]).prod()
# 1.0
您可以通过设置相应的关键字来规避此问题:
pd.Series([np.NaN, np.NaN]).prod(skipna=False)
# nan
对于您的情况,您可以将其应用为
print(df)
Score 1 Score 2 Score 3
2000-01-01 18 19 1.0
2000-01-02 9 18 2.0
2000-01-03 10 4 3.0
2000-01-04 4 15 4.0
2000-01-05 12 1 NaN
2000-01-06 1 3 NaN
2000-01-07 8 9 NaN
print(df.resample("3d").agg(pd.DataFrame.prod, skipna=False))
Score 1 Score 2 Score 3
2000-01-01 1620 1368 6.0
2000-01-04 48 45 NaN
2000-01-07 8 9 NaN
请注意,如果 window 包含至少一个 NaN
值,这会将所有重采样时间 windows 设置为 NaN
- 我更改了示例 df
微微地表明。您可以 apply
a lambda
代替,检查是否至少有一个元素不是 NaN
:
print(df.resample("3d").apply(lambda x: x.prod() if any(x.notnull()) else np.nan))
Score 1 Score 2 Score 3
2000-01-01 1620 1368 6.0
2000-01-04 48 45 4.0
2000-01-07 8 9 NaN
我正在处理一个相当大的数据集。在将 resample 命令与转换方法“prod”(乘法)结合使用后,我意识到我的 NaN 值已更改为 1,这不是我想要的。举个例子:
# build random dataframe with one column containing NaN
import pandas as pd
import numpy as np
index = pd.date_range('1/1/2000', periods=7, freq='d')
df = pd.DataFrame(index = index, columns = ["Score 1", "Score 2", "Score 3"])
df["Score 1"] = np.random.randint(1,20,size=7)
df["Score 2"] = np.random.randint(1,20,size=7)
df["Score 3"] = [1, 2, 3, np.NaN, np.NaN, np.NaN, np.NaN]
print(df)
Score 1 Score 2 Score 3
2000-01-01 6 7 1.0
2000-01-02 2 15 2.0
2000-01-03 8 19 3.0
2000-01-04 14 19 NaN
2000-01-05 17 8 NaN
2000-01-06 15 6 NaN
2000-01-07 12 18 NaN
现在假设我想使用“prod”转换方法将我的 Dataframe 从每日频率重新采样为 3 天频率。我这样做:
df.resample("3d").agg("prod")
print(df)
Score 1 Score 2 Score 3
2000-01-01 96 1995 6.0
2000-01-04 3570 2052 1.0
2000-01-07 12 18 1.0
看着“Score 3”这一列,我的NaN值突然变成了1,这让我很惊讶。这意味着当将 NaN 相互相乘时,我会得到 =1。有人知道为什么 NaN 的乘法正好等于 1 吗?我可以做些什么来保持 NaN 值以防它与自身相乘?
在此先致谢,非常感谢任何帮助
pandas.DataFrame.prod
函数 (docs) 默认将 NaN
设置为 1:
pd.Series([np.NaN, np.NaN]).prod()
# 1.0
您可以通过设置相应的关键字来规避此问题:
pd.Series([np.NaN, np.NaN]).prod(skipna=False)
# nan
对于您的情况,您可以将其应用为
print(df)
Score 1 Score 2 Score 3
2000-01-01 18 19 1.0
2000-01-02 9 18 2.0
2000-01-03 10 4 3.0
2000-01-04 4 15 4.0
2000-01-05 12 1 NaN
2000-01-06 1 3 NaN
2000-01-07 8 9 NaN
print(df.resample("3d").agg(pd.DataFrame.prod, skipna=False))
Score 1 Score 2 Score 3
2000-01-01 1620 1368 6.0
2000-01-04 48 45 NaN
2000-01-07 8 9 NaN
请注意,如果 window 包含至少一个 NaN
值,这会将所有重采样时间 windows 设置为 NaN
- 我更改了示例 df
微微地表明。您可以 apply
a lambda
代替,检查是否至少有一个元素不是 NaN
:
print(df.resample("3d").apply(lambda x: x.prod() if any(x.notnull()) else np.nan))
Score 1 Score 2 Score 3
2000-01-01 1620 1368 6.0
2000-01-04 48 45 4.0
2000-01-07 8 9 NaN