假设我有一些格式为
的数据框 id time value
0 100 2012-04-01 2.3
1 100 2012-04-02 3.4
2 100 2012-04-03 1.4
3 100 2012-04-04 5.6
4 200 2012-04-01 NaN
5 200 2012-04-02 2.9
6 200 2012-04-03 2.8
7 200 2012-04-04 1.9
8 300 2012-04-01 3.1
9 300 2012-04-02 NaN
10 300 2012-04-03 2.5
11 300 2012-04-04 1.2
所以我们有时间序列的id(这里是100,200,300),对于每个时间序列,我们有相应的4个不同时间步长的值(2012-04-01到2012-04-04)。
我想创建一个函数来获取这样的数据帧,将其转动然后对行进行求和。但是,我希望此函数具有一个参数,该参数决定如何在其中一个值为nan值的情况下求和。我有3个案例:
我的尝试
首先,看here我知道我可以使用df.pivot('time', 'id', 'value')
获取
time 100 200 300
2012-04-01 2.3 3.0 3.1
2012-04-02 3.4 2.9 4.2
2012-04-03 1.4 2.8 2.5
2012-04-04 5.6 1.9 1.2
然后该功能看起来像
def pivot_sum(df, method = 'zero'):
# NaN are treated as zero: a + b + NaN = a + b
if method == 'zero':
return pd.DataFrame(df.groupby('time')['value'].sum())
else:
# First we pivot it
pivoted = df.pivot('time', 'id', 'value')
# Then we choose
if method == 'nan_make_zero_sum':
# Do something
elif method == 'nan_make_nan_sum':
# DO something else
我完全不知道如何继续。我注意到使用groupby选项的行为就好像nan值被视为零。但是,我不知道如何实施其他的。
注意:我注意到新版本的pandas有一个参数min_count
可能很有用(https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.sum.html),但我有0.21版本,由于其他问题,更改版本不是一个很好的解决方案。
修改
我设法编写它以便它适用于pandas版本0.22,但是我想知道如何编写类似于以前版本的函数。无论如何它在这里
def sum_values(df, method = 'skip'):
if method == 'skip':
# Then we treat NaN values as zeros
return pd.DataFrame(df.groupby('time')['value'].sum())
else:
# First we pivot the df
df_pivoted = df.pivot('time', 'id', 'value')
# Then we check
if method == 'nan_sum':
return pd.DataFrame(df_pivoted.sum(axis = 1, min_count = df_pivoted.shape[1])).rename(columns = {0:'value'})
elif method == 'zero_sum':
# do the same as above
return pd.DataFrame(df_pivoted.sum(axis = 1, min_count = df_pivoted.shape[1])).rename(columns = {0:'value'}).fillna(0)
编辑2 - 看起来像什么
鉴于上述功能,这就是流程的样子。
我有一个数据框
id time value
0 100 2012-04-01 2.3
1 100 2012-04-02 3.4
2 100 2012-04-03 1.4
3 100 2012-04-04 5.6
4 200 2012-04-01 NaN
5 200 2012-04-02 2.9
6 200 2012-04-03 2.8
7 200 2012-04-04 1.9
8 300 2012-04-01 3.1
9 300 2012-04-02 NaN
10 300 2012-04-03 2.5
11 300 2012-04-04 1.2
并应用上述功能
sum_values(df, method = 'skip')
返回
value
time
2012-04-01 5.4
2012-04-02 6.3
2012-04-03 6.7
2012-04-04 8.7
sum_values(df, method = 'nan_sum')
返回
value
time
2012-04-01 NaN
2012-04-02 NaN
2012-04-03 6.7
2012-04-04 8.7
sum_values(df, method = 'zero_sum')
返回
value
time
2012-04-01 0.0
2012-04-02 0.0
2012-04-03 6.7
2012-04-04 8.7
答案 0 :(得分:1)
我创建了以下3个函数,可以提供所需的输出:
功能1
import numpy as np
def sum_val(df):
df1=df.copy()
df1['value'] = pd.to_numeric(df1['value'], errors='coerce')
df2=df1.fillna(0.0)
df2['sum_nan']=df2.groupby(['time_val']).transform('sum')
df3=df2.drop('value', inplace=False, axis=1)
df4=df3.drop_duplicates()
return (df4)
sum_val(df)
输出:
time_val sum_nan
0 2012-04-01 5.4
1 2012-04-02 6.3
2 2012-04-03 6.7
3 2012-04-04 8.7
功能2
def sum_nan(df):
df1=pd.DataFrame()
df1=df.copy()
df1['sum_nan']=df1.groupby(['time_val']).transform('sum')
df2=df1.drop('value', inplace=False, axis=1)
df2=df2.drop_duplicates()
return df2
sum_nan(df)
输出:
time_val sum_nan
0 2012-04-01 NaN
1 2012-04-02 NaN
2 2012-04-03 6.7
3 2012-04-04 8.7
功能3
def sum_0(df):
df1=pd.DataFrame()
df1=df.copy()
df1['sum_nan']=df1.groupby(['time_val']).transform('sum')
df2=df1.drop('value', inplace=False, axis=1)
df2=df2.replace(np.nan,0)
df3=df2.drop_duplicates()
return(df3)
sum_0(df)
输出:
time_val sum_nan
0 2012-04-01 0.0
1 2012-04-02 0.0
2 2012-04-03 6.7
3 2012-04-04 8.7