如何用 None - python, pandas 数据帧替换字符串值
How to replace a string value with None - python, pandas dataframe
我有一个比我在这里展示的更大的数据框,但我想做的是在一个系列(或者甚至更好的整个数据框)中任何有特定价值的地方将该值更改为 None。我需要这些是 None 这样我就可以将数据帧写入数据库并且它将被识别为空。
series = (['2014/06/05 13:03:56', '2014/07/23 13:03:56', None, '2014/08/21 13:03:56'])
data = pd.DataFrame(series)
0 2014/06/05 13:03:56
1 2014/07/23 13:03:56
2 None
3 2014/08/21 13:03:56
data = pd.to_datetime(data[0], coerce=True)
data
0 2014-06-05 13:03:56
1 2014-07-23 13:03:56
2 NaT
3 2014-08-21 13:03:56
Name: 0, dtype: datetime64[ns]
data = data.map(str)
data
0 2014-06-05 13:03:56
1 2014-07-23 13:03:56
2 NaT
3 2014-08-21 13:03:56
Name: 0, dtype: object
data.replace(to_replace='NaT', value=None)
0 2014-06-05 13:03:56
1 2014-07-23 13:03:56
2 2014-07-23 13:03:56
3 2014-08-21 13:03:56
Name: 0, dtype: object
在上面的示例中,当我尝试替换 'NaT' 时,数据框实际上用前面的值而不是 None 填充值。这无济于事,因为它需要 None。在我使用的实际数据框中,这通常会抛出一个类型错误,告诉我我不能用 method pad 替换 None。我在这里使用的是日期时间系列,但实际上我需要它的不仅仅是日期时间系列。它似乎应该是 pandas 的基本功能,但我找不到答案。
谢谢,
科林
首先,您的代码无法正常工作的原因是那些 NaT
值不是字符串 'NaT'
,而是值 pd.NaT
。但由于我认为修复它实际上不会给你想要的东西,所以我们暂时忽略它。
A Pandas DataFrame
,就像它所基于的 NumPy ndarray
一样,是类型化的低级值的紧凑数组。这就是它小巧、快速和类型安全的原因。但这本质上意味着它只能存储指定类型的值。 None
不是 datetime64[ns]
类型的值。
更具体地说,datetime64[ns]
只能保存表示日期时间的 64 位整数,自纪元以来的纳秒数,而 None
不是 64 位整数。
Pandas确实有一个特殊的值来处理这个,叫做NaT
,对于"Not a Time";这是您可以在任何类型的日期时间字段中获得的最接近 None
的东西(就像更熟悉的 NaN
用于浮点数)。这就是您已经拥有的。
与此同时,Pandas 在各个不同的地方对 None
提供特殊支持,这些地方试图做您 经常 想要的事情——存储 NaN/NaT/0 ,或重复最后一个值,或其他各种事情。但是,如果这不是您想要的,那也没什么用。
如果您确实需要 None
,唯一的方法是存储正常的盒装 Python 对象而不是键入的低级值,您可以使用 dtype=object
。然后,您可以将任何 Python 值粘贴到任何元素中,当然包括 None
。
但这样做很大程度上违背了使用 Pandas 和 NumPy 的目的。您可能最好使用 NaT
,并更改其余代码 — 在您当前期望 None
的地方期望 NaT
,或者包装 DataFrame
在提取或打印输出期间将 NaT
值转换为 None
的东西中。
为了完整性,如果你想变得疯狂,没有什么能阻止你定义一个 optionaldatetime64[ns]
dtype 就像 datetime64[ns]
除了它使用为 NaT
保留的特殊值意思是 None
代替。或者它甚至可以保留另一个特殊值或一整位来表示 None
,同时单独保留 NaT
。无论哪种方式,这都会有很多工作,并且它会完全破坏任何依赖于日期时间算术的操作(d - NaT == NaT
对于任何 d
,但 d - None
是一个 TypeError
对于任何 d
...),最终它不会比我能想到的任何目的的包装器解决方案更好...
最终,这满足了我的需要。我不认为 map(str) 在我为这个问题给出的代码中工作,但它在我将它分配给一个字段而不是整个数据帧的地方工作。
def change_date_to_string(field):
data[field] = data[field].map(str)
data[field].loc[data[field] == 'NaT'] = None
change_date_to_string(field='usr_datetime')
我有一个比我在这里展示的更大的数据框,但我想做的是在一个系列(或者甚至更好的整个数据框)中任何有特定价值的地方将该值更改为 None。我需要这些是 None 这样我就可以将数据帧写入数据库并且它将被识别为空。
series = (['2014/06/05 13:03:56', '2014/07/23 13:03:56', None, '2014/08/21 13:03:56'])
data = pd.DataFrame(series)
0 2014/06/05 13:03:56
1 2014/07/23 13:03:56
2 None
3 2014/08/21 13:03:56
data = pd.to_datetime(data[0], coerce=True)
data
0 2014-06-05 13:03:56
1 2014-07-23 13:03:56
2 NaT
3 2014-08-21 13:03:56
Name: 0, dtype: datetime64[ns]
data = data.map(str)
data
0 2014-06-05 13:03:56
1 2014-07-23 13:03:56
2 NaT
3 2014-08-21 13:03:56
Name: 0, dtype: object
data.replace(to_replace='NaT', value=None)
0 2014-06-05 13:03:56
1 2014-07-23 13:03:56
2 2014-07-23 13:03:56
3 2014-08-21 13:03:56
Name: 0, dtype: object
在上面的示例中,当我尝试替换 'NaT' 时,数据框实际上用前面的值而不是 None 填充值。这无济于事,因为它需要 None。在我使用的实际数据框中,这通常会抛出一个类型错误,告诉我我不能用 method pad 替换 None。我在这里使用的是日期时间系列,但实际上我需要它的不仅仅是日期时间系列。它似乎应该是 pandas 的基本功能,但我找不到答案。
谢谢, 科林
首先,您的代码无法正常工作的原因是那些 NaT
值不是字符串 'NaT'
,而是值 pd.NaT
。但由于我认为修复它实际上不会给你想要的东西,所以我们暂时忽略它。
A Pandas DataFrame
,就像它所基于的 NumPy ndarray
一样,是类型化的低级值的紧凑数组。这就是它小巧、快速和类型安全的原因。但这本质上意味着它只能存储指定类型的值。 None
不是 datetime64[ns]
类型的值。
更具体地说,datetime64[ns]
只能保存表示日期时间的 64 位整数,自纪元以来的纳秒数,而 None
不是 64 位整数。
Pandas确实有一个特殊的值来处理这个,叫做NaT
,对于"Not a Time";这是您可以在任何类型的日期时间字段中获得的最接近 None
的东西(就像更熟悉的 NaN
用于浮点数)。这就是您已经拥有的。
与此同时,Pandas 在各个不同的地方对 None
提供特殊支持,这些地方试图做您 经常 想要的事情——存储 NaN/NaT/0 ,或重复最后一个值,或其他各种事情。但是,如果这不是您想要的,那也没什么用。
如果您确实需要 None
,唯一的方法是存储正常的盒装 Python 对象而不是键入的低级值,您可以使用 dtype=object
。然后,您可以将任何 Python 值粘贴到任何元素中,当然包括 None
。
但这样做很大程度上违背了使用 Pandas 和 NumPy 的目的。您可能最好使用 NaT
,并更改其余代码 — 在您当前期望 None
的地方期望 NaT
,或者包装 DataFrame
在提取或打印输出期间将 NaT
值转换为 None
的东西中。
为了完整性,如果你想变得疯狂,没有什么能阻止你定义一个 optionaldatetime64[ns]
dtype 就像 datetime64[ns]
除了它使用为 NaT
保留的特殊值意思是 None
代替。或者它甚至可以保留另一个特殊值或一整位来表示 None
,同时单独保留 NaT
。无论哪种方式,这都会有很多工作,并且它会完全破坏任何依赖于日期时间算术的操作(d - NaT == NaT
对于任何 d
,但 d - None
是一个 TypeError
对于任何 d
...),最终它不会比我能想到的任何目的的包装器解决方案更好...
最终,这满足了我的需要。我不认为 map(str) 在我为这个问题给出的代码中工作,但它在我将它分配给一个字段而不是整个数据帧的地方工作。
def change_date_to_string(field):
data[field] = data[field].map(str)
data[field].loc[data[field] == 'NaT'] = None
change_date_to_string(field='usr_datetime')