我正在尝试执行以下操作:
pd.concat([A,B], axis = 1).groupby("status_reason")["closing_time"].mean()
哪里
示例:
In : A.head(5)
Out:
0 -1 days +11:35:00
1 -10 days +07:13:00
2 NaT
3 NaT
4 NaT
Name: closing_time, dtype: timedelta64[ns]
In : B.head(5)
Out:
0 Won
1 Canceled
2 In Progress
3 In Progress
4 In Progress
Name: status_reason, dtype: object
发生以下错误:
DataError: No numeric types to aggregate
请注意:我试图对均值进行平均,甚至隔离每个类别
现在,我在网上看到了一些类似于我的问题,所以我尝试了这个问题:
pd.to_timedelta(pd.concat([pd.to_numeric(A),B], axis = 1).groupby("status_reason")["closing_time"].mean())
这只是将Timedelta转换为int64,反之亦然。但是结果很奇怪(数字太高了)
为了调查这种情况,我编写了以下代码:
xxx = pd.concat([A,B], axis = 1)
xxx.closing_time.mean()
#xxx.groupby("status_reason")["closing_time"].mean()
第二行有效,但没有将Timedelta转换为Int64。第三行无效,并再次返回DataError。
我在这里很困惑!我是什么小姐?
我想查看每个“状态原因”的“关闭时间”的平均值!
编辑
如果我尝试执行此操作:(隔离具有特定状态的行而不进行分组)
yyy = xxx[xxx["status_reason"] == "In Progress"]
yyy["closing_time"].mean()
结果是:
Timedelta('310 days 21:18:05.454545')
但是,如果我这样做:(用特定的状态分组隔离行)
yyy = xxx[xxx["status_reason"] == "In Progress"]
yyy.groupby("status_reason")["closing_time"].mean()
结果再次是:
DataError: No numeric types to aggregate
最后,如果我这样做:(转换并转换回)(请致电:特殊示例)
yyy = xxx[xxx["status_reason"] == "In Progress"]
yyy.closing_time = pd.to_numeric (yyy.closing_time)
pd.to_timedelta(yyy.groupby("status_reason")["closing_time"].mean())
我们回到我注意到的第一个问题:
status_reason
In Progress -105558 days +10:08:05.605064
Name: closing_time, dtype: timedelta64[ns]
EDIT2
如果我这样做:(转换为秒然后转换回去)
yyy = xxx[xxx["status_reason"] == "In Progress"]
yyy.closing_time = A.dt.seconds
pd.to_timedelta(yyy.groupby("status_reason")["closing_time"].mean(), unit="s" )
结果是
status_reason
In Progress 08:12:38.181818
Name: closing_time, dtype: timedelta64[ns]
如果删除NaN或将其填充为0,也会发生相同的结果:
yyy = xxx[xxx["status_reason"] == "In Progress"].dropna()
yyy.closing_time = A.dt.seconds
pd.to_timedelta(yyy.groupby("status_reason")["closing_time"].mean(), unit="s" )
但是数字与我们在第一次编辑中看到的数字有很大不同! (特殊示例)
-105558 days +10:08:05.605064
此外,让我使用dropna()运行相同的代码(特殊示例):
310 days 21:18:05.454545
再次,让我们使用fillna(0)运行相同的代码(特殊示例):
3 days 11:14:22.819472
这无济于事。我可能应该准备导出这些数据,并将其发布到某个地方:Here we go
答案 0 :(得分:1)
问题可能是In Progress
只有NaT
的时间,而groupby().mean()
可能不允许。这是测试:
df = pd.DataFrame({'closing_time':['11:35:00', '07:13:00', np.nan,np.nan, np.nan],
'status_reason':['Won','Canceled','In Progress', 'In Progress', 'In Progress']})
df.closing_time = pd.to_timedelta(df.closing_time)
df.groupby('status_reason').closing_time.mean()
给出确切的错误。要克服这个问题,请执行以下操作:
def custom_mean(x):
try:
return x.mean()
except:
return pd.to_timedelta([np.nan])
df.groupby('status_reason').closing_time.apply(custom_mean)
给出:
status_reason
Canceled 07:13:00
In Progress NaT
Won 11:35:00
Name: closing_time, dtype: timedelta64[ns]
答案 1 :(得分:1)
我不能说为什么groupby的mean()方法不起作用,但是对您的代码进行以下稍作修改应该起作用:首先,使用total_seconds()方法将timedelta列转换为秒,然后使用groupby和mean,然后将秒转换为timedelta再次:
pd.to_timedelta(pd.concat([ A.dt.total_seconds(), B], axis = 1).groupby("status_reason")["closing_time"].mean(), unit="s")
例如下面的数据框代码-
df = pd.DataFrame({'closing_time':['2 days 11:35:00', '07:13:00', np.nan,np.nan, np.nan],'status_reason':['Won','Canceled','In Progress', 'In Progress', 'In Progress']})
df.loc[:,"closing_time"] = \
pd.to_timedelta(df.closing_time).dt.days*24*3600 \
+ pd.to_timedelta(df.closing_time).dt.seconds
# or alternatively use total_seconds() to get total seconds in timedelta as follows
# df.loc[:,"closing_time"] = pd.to_timedelta(df.closing_time).dt.total_seconds()
pd.to_timedelta(df.groupby("status_reason")["closing_time"].mean(), unit="s")
产生
status_reason
Canceled 0 days 07:13:00
In Progress NaT
Won 2 days 11:35:00
Name: closing_time, dtype: timedelta64[ns]
答案 2 :(得分:1)
通过阅读有关Github here的有关此问题的讨论,可以通过如下方式为均值计算指定numeric_only = False来解决此问题
pd.concat([A,B], axis = 1).groupby("status_reason")["closing_time"] \
.mean(numeric_only=False)
答案 3 :(得分:0)
经过一些调查,这是我发现的东西:
大多数困惑来自以下事实:在一个案例中,我调用了SeriesGroupBy.mean(),而在另一案例中,我调用了Series.mean()
这些功能实际上是不同的,并且具有不同的行为。我没有意识到
第二个重要点是,在处理NaNs值时,转换为数字或秒将导致完全不同的行为。
要克服这种情况,您要做的第一件事就是确定如何处理NaN值。最佳方法取决于我们要实现的目标。就我而言,即使是简单的分类结果也可以,因此我可以执行以下操作:
import datetime
def define_time(row):
if pd.isnull(row["closing_time"]):
return "Null"
elif row["closing_time"] < datetime.timedelta(days=100):
return "<100"
elif row["closing_time"] > datetime.timedelta(days=100):
return ">100"
time_results = pd.concat([A,B], axis = 1).apply(lambda row:define_time(row), axis = 1)
最后的结果是这样的:
In :
time_results.value_counts()
Out :
>100 1452
<100 1091
Null 1000
dtype: int64