Fed*_*ato 5 python type-conversion timedelta pandas
我正在尝试执行以下操作:
pd.concat([A,B], axis = 1).groupby("status_reason")["closing_time"].mean()
Run Code Online (Sandbox Code Playgroud)
在哪里
例子:
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
Run Code Online (Sandbox Code Playgroud)
出现以下错误:
DataError: No numeric types to aggregate
Run Code Online (Sandbox Code Playgroud)
请注意:我尝试执行平均值,甚至隔离每个类别
现在,我在网上看到了一些与我类似的问题,所以我尝试了以下方法:
pd.to_timedelta(pd.concat([pd.to_numeric(A),B], axis = 1).groupby("status_reason")["closing_time"].mean())
Run Code Online (Sandbox Code Playgroud)
这只是将 Timedelta 转换为 int64,反之亦然。但结果很奇怪(数字太高)
为了排查情况,我编写了如下代码:
xxx = pd.concat([A,B], axis = 1)
xxx.closing_time.mean()
#xxx.groupby("status_reason")["closing_time"].mean()
Run Code Online (Sandbox Code Playgroud)
第二行工作正常,无需将 Timedelta 转换为 Int64。第三行不起作用,并再次返回 DataError。
我在这里很困惑!我错过了什么?
我想查看每个“状态原因”的“关闭时间”的平均值!
编辑
如果我尝试这样做:(隔离具有特定状态的行而不进行分组)
yyy = xxx[xxx["status_reason"] == "In Progress"]
yyy["closing_time"].mean()
Run Code Online (Sandbox Code Playgroud)
结果是:
Timedelta('310 days 21:18:05.454545')
Run Code Online (Sandbox Code Playgroud)
但如果我这样做:(隔离具有特定状态分组的行)
yyy = xxx[xxx["status_reason"] == "In Progress"]
yyy.groupby("status_reason")["closing_time"].mean()
Run Code Online (Sandbox Code Playgroud)
结果又是:
DataError: No numeric types to aggregate
Run Code Online (Sandbox Code Playgroud)
最后,如果我这样做:(转换并转换回来)(让我们称之为:特殊示例)
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())
Run Code Online (Sandbox Code Playgroud)
我们回到我注意到的第一个问题:
status_reason
In Progress -105558 days +10:08:05.605064
Name: closing_time, dtype: timedelta64[ns]
Run Code Online (Sandbox Code Playgroud)
编辑2
如果我这样做:(转换为秒并转换回来)
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" )
Run Code Online (Sandbox Code Playgroud)
结果是
status_reason
In Progress 08:12:38.181818
Name: closing_time, dtype: timedelta64[ns]
Run Code Online (Sandbox Code Playgroud)
如果我删除 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" )
Run Code Online (Sandbox Code Playgroud)
但这些数字与我们在第一次编辑中看到的非常不同!(特殊示例)
-105558 days +10:08:05.605064
Run Code Online (Sandbox Code Playgroud)
另外,让我使用 dropna()运行相同的代码(特殊示例):
310 days 21:18:05.454545
Run Code Online (Sandbox Code Playgroud)
再次,让我们使用 fillna(0)运行相同的代码(特殊示例):
3 days 11:14:22.819472
Run Code Online (Sandbox Code Playgroud)
这无处可去。我可能应该准备这些数据的导出,并将它们发布到某个地方: 我们开始吧
经过一些调查,我发现以下内容:
大多数混乱来自这样一个事实:在一种情况下我调用 SeriesGroupBy.mean() 而在另一种情况下调用 Series.mean()
这些函数实际上是不同的并且具有不同的行为。我没有意识到
第二个要点是,在处理 NaN 值时,转换为数字或秒会导致完全不同的行为。
为了克服这种情况,您要做的第一件事就是决定如何处理 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)
Run Code Online (Sandbox Code Playgroud)
最终结果是这样的:
In :
time_results.value_counts()
Out :
>100 1452
<100 1091
Null 1000
dtype: int64
Run Code Online (Sandbox Code Playgroud)