【问题标题】:Python PANDAS: New Column, Apply Unique Value To All RowsPython PANDAS:新列,对所有行应用唯一值
【发布时间】:2015-05-29 15:07:27
【问题描述】:

作为一个在数据分析领域花费更多时间而不是正确编程的人,只是在寻找一种最佳方法(向你们所有人致敬)。非常简单的大型 ETL 项目,但在 Python 中手动编码,这是第一次。固定宽度文件已成功读入初始 PANDAS df。

我正在尝试添加一个带有静态月末日期值(例如 2014 年 1 月 31 日)的新列,以指示“数据月份”以进行进一步的 EDW 处理。最终,我将使用 datetime/timedelta 功能将此值作为我在实用程序服务器上 CRON 时自动生成的值传递。

我的困惑似乎是关于使用哪个函数(apply、mapapply 等),如果我需要引用原始 df 中的索引值以将完全不相关的值应用于初始 df,并且最优化, pythonic方式来完成这个。

当前参考:“Python for Data Analysis”,PANDAS Docs。谢谢!

编辑

下面是一些固定宽度数据的小例子:

5151022314 
5113 22204
111  20018

这是一些将其读入 PANDAS df 的代码:

import pandas as pd
import numpy as np

path = 'C:\Users\Office\Desktop\example data.txt' 
widths = [2, 3, 5]
names = (['STATE_CD', 'CNTY_CD', 'ZIP_CD',])

df = pd.read_fwf(path, names=names, widths=widths, header=0)

对于上面的示例日期,这应该返回类似这样的 df:

STATE_CD,CNTY_CD,ZIP_CD
51,510,22314     
51,1  ,22204
11,3  ,20018

我要做的是为所有行添加一个像这样的列“DATA_MM”:

STATE_CD,CNTY_CD,ZIP_CD, DATA_MM
51,510,22314,2014-01-31     
51,1  ,22204,2014-01-31
11,3  ,20018,2014-01-31

最终,我希望利用这样的东西来生成在这个月度工作开始时自动应用的价值:

import datetime
today = datetime.date.today()
first = datetime.date(day=1, month=today.month, year=today.year)
lastMonth = first - datetime.timedelta(days=1)
print lastMonth.strftime("%Y-%m-%d")

【问题讨论】:

  • 给我们一个可复制粘贴运行的完整最小示例,以及它应该返回的结果示例。 (产生这些也是很好的编程实践。)
  • 当你说“唯一”时,你是指每一行一个值,还是整列一个值?
  • 编辑@cphlewis 感谢您的及时回复。根据您的要求,我添加了一个基本示例。 @ASGM 我的意思是整列每一行的值都相同

标签: python python-2.7 date pandas etl


【解决方案1】:

如果您想用不依赖于原始 DataFrame 的新值填充列,则无需引用原始索引。您可以通过简单地为其分配新值来填充新列:

df["DATA_MM"] = date

您可以通过使用datetimecalendar 获取当月的最后一天:

import datetime
import calendar

today = datetime.date.today()
y = today.year
m = today.month
eom = datetime.date(y, m, calendar.monthrange(y, m)[1])

df["DATA_MM"] = eom

monthrange 返回一个包含该月第一天和最后一天的元组,因此 [1] 引用该月的最后一天。您也可以使用@Alexander 的方法来查找最后一天的日期,并将其直接分配给列而不是applying。

【讨论】:

  • 好问题。这绝对是一个简单的案例。我认为在您建议的情况下,我需要创建一个包含所有月末日期的字典,并使用某种类型的计数器迭代它们,如果这将自动每月运行,如果我(可能)错了,请纠正我?
  • 对不起,我想我还是有点糊涂。你的意思是你想每个月添加一个新列?如果是这样,也许这会起作用:df["DATA_{0}".format(date.month)] = date?是的,您可以遍历字典来获取这些日期。如果这确实是您的意思,我可以将其添加到答案中。
  • 没问题。对于任何歧义,我深表歉意。 ETL 过程可能是特殊的。我想每个月创建/将此列添加到新数据文件中。抓取/抓取新文件并读入新的 df,再次添加“数据月”列,并将此值更新为新的 EOM 并应用于所有新记录(2014/01/31 变为 2014/02/28),并且然后我将剩下的无关处理用于我的管道。这是否提供了足够的清晰度?我想我最好避免使用字典方法,并且能够通过日期时间库功能获取日期。 ——
  • 我明白了,我误解了你为什么需要字典。我已经用一种稍微详细一点的方法来确定月末日期,但我希望它更容易阅读。如果要使用上个月的最后一天,可以将m改为m - 1
【解决方案2】:

假设您的 DataFrame 被命名为 df 并且它有一个时间戳的日期列,您希望获取其月末 (EOM) 值:

df['EOM date'] = df.date.apply(lambda x: x.to_period('M').to_timestamp('M'))

您将对象强制转换为 Pandas Period 对象,然后返回到月底时间戳,因此它可能不是最有效的方法。

这是一个带有一些性能统计数据的替代实现:

dates = pd.date_range('2000-1-1', '2015-1-1')
df = pd.DataFrame(dates, columns=['date'])

%%timeit
df.date.apply(lambda x: x.to_period('M').to_timestamp('M'))
10 loops, best of 3: 161 ms per loop

%%timeit
df.date.apply(lambda x: x + pd.datetools.MonthEnd())
1 loops, best of 3: 177 ms per loop

只需从当前日期获取月末日期的 DATETIME.DATE(根据下面的请求)可以实现如下:

pd.Timestamp(dt.datetime.now()).to_period('M').to_timestamp('M').date()

【讨论】:

  • @Alexander 谢谢你的选择。我会做一些测试。是否可以轻松地将它们作为 DATE 或 DATETIME 而不是 TIMESTAMP 带回来?只是为了集成而在我们的 EDW 中使用的约定。
  • 只需在末尾附加 .date():pd.Timestamp(dt.datetime.now()).to_period('M').to_timestamp('M').date()跨度>
  • 另外,如果您只想为一列分配一个通过您的 cron 作业提供的月末日期值,而不是在给定一列不同日期值的情况下计算 EOM 日期(如您所暗示的那样)编辑),然后只需使用 ASGM 的分配建议:df['EOM_date'] = pd.Timestamp(dt.datetime.now()).to_period('M').to_timestamp('M').date()跨度>
  • 啊,抱歉,我并不是要暗示我会从我编辑时已经存在的列中计算 EOM 日期(我的完整测试用例数据集没有相关的日期字段可以尝试这种方法)。我只是指出了一种我一直在考虑计算整块布的值的方法,然后每当通过简单的 SHEBANG 行初始化 cron 作业时应用该值。我会试试这个并回复你。认为它可能会奏效。
  • 您的编辑暗示我曾以为您想要日期列表的 EOM 值,而您似乎只想要一个值。
猜你喜欢
  • 1970-01-01
  • 2020-02-20
  • 2023-02-19
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-18
  • 2021-11-25
相关资源
最近更新 更多