【问题标题】:Occurrence of a number between two specific datetime ranges in PandasPandas 中两个特定日期时间范围之间的数字出现
【发布时间】:2020-04-14 19:49:32
【问题描述】:

我有 2 个 CSV 文件,如下所示。

  1. 我想要一个新专栏Difference,其中...
    • 如果手机号码出现在Book_date...App_date的日期范围内:Difference=区别App_dateOccur_date
    • 或 NaN,如果它不在该日期范围内。
  2. 我还想根据唯一的类别和 mobile_number 对其进行过滤

csv_1

Mobile_Number    Book_Date       App_Date

503477334    2018-10-12       2018-10-18
506002884    2018-10-12       2018-10-19
501022162    2018-10-12       2018-10-16
503487338    2018-10-13       2018-10-13
506012887    2018-10-13       2018-10-21
503427339    2018-10-14       2018-10-17

csv_2

Mobile_Number    Occur_Date    

503477334        2018-10-16
506002884        2018-10-21
501022162        2018-10-15
503487338        2018-10-13
501428449        2018-10-18
506012887        2018-10-14

我想要 csv_1 中的一个新列,其中如果手机号码出现在 csv_2 中 Book_date 和 App_date 的日期范围内,App_date 与 Occur_date 或 NaN 之间的差异(如果它不在该日期范围内)。输出应该是

输出

Mobile_Number    Book_Date       App_Date   Difference

503477334    2018-10-12       2018-10-18       2
506002884    2018-10-12       2018-10-19      -2
501022162    2018-10-12       2018-10-16       1
503487338    2018-10-13       2018-10-13       0
506012887    2018-10-13       2018-10-21       7 
503427339    2018-10-14       2018-10-17       NaN

编辑:

如果我想根据上述两个 csv 文件上的唯一类别和 mobile_number 对其进行过滤。如何做到这一点?

csv_1

Category     Mobile_Number   Book_Date       App_Date

A              503477334    2018-10-12       2018-10-18
B              503477334    2018-10-07       2018-10-16
C              501022162    2018-10-12       2018-10-16
A              503487338    2018-10-13       2018-10-13
C              506012887    2018-10-13       2018-10-21
E              503427339    2018-10-14       2018-10-17

csv_2

Category     Mobile_Number    Occur_Date    

A              503477334        2018-10-16
B              503477334        2018-10-13
A              501022162        2018-10-15
A              503487338        2018-10-13
F              501428449        2018-10-18
C              506012887        2018-10-14

我希望根据 Mobile_Number 和类别过滤输出

输出

Category     Mobile_Number    Book_Date       App_Date   Difference

A              503477334    2018-10-12       2018-10-18       2
B              503477334    2018-10-07       2018-10-16       3
C              501022162    2018-10-12       2018-10-16       NaN
A              503487338    2018-10-13       2018-10-13       0
C              506012887    2018-10-13       2018-10-21       7 
E              503427339    2018-10-14       2018-10-17       NaN

【问题讨论】:

  • pandas 有 Series.between() 运算符。查看现有的 1229 个问题 [pandas] between date。此外,当您读取日期时间列时或之后将它们转换为日期时间通常会有所帮助,将它们作为字符串并没有多大用处。
  • dPac 很难理解你的问题,它分散在多个数据块之间,你能重写第一段中的问题吗?想必你先在Mobile_Number上加入csv_1, _2,然后过滤.between('Book_date'...'App_date')。但是您想按类别过滤该序列中的哪个位置?这很令人困惑,因为您说“根据唯一类别对其进行过滤”,但您当前的输出对于不同的 Book_Date,App_Date 值有多个类别 ==A'、'C' 的结果。还有,Category是什么,从哪里来的?...
  • ...您是否只是为中间结果分配了任意 Category 值(例如 App_Date, Book_Date?? 的不同组合)还是来自其他地方?无论如何,请编辑您的问题以重述,目前尚不清楚。因此很难找到现有的重复/相关问题。
  • 我试图编辑它以清楚地说明问题,并在顶部。 a) 无论您的意思是“时间范围”、“日期范围”还是“日期时间范围”,请尽量保持一致。 b) 我们仍然不知道Category 来自哪里,是来自另一个文件,还是只是为您的临时结果分配了一些默认值? c) 当您不断提及“来自 csv_2 的列”...“在 csv_1 中创建一个新列”时,这会分散注意力。。为什么不一开始就将数据加入一个数据框df? (您始终可以使用to_csv(..., columns) 写出单独的列集以分隔CSV 文件)
  • ...但是请告诉我们Category 来自哪里?!

标签: python pandas datetime date-arithmetic


【解决方案1】:

Series.map 用于与Mobile_Number 匹配的新Series,对于列之间的测试值使用Series.between,然后使用numpy.where 通过掩码分配值:

df1['Book_Date'] = pd.to_datetime(df1['Book_Date'])
df1['App_Date'] = pd.to_datetime(df1['App_Date'])
df2['Occur_Date'] = pd.to_datetime(df2['Occur_Date'])

s1 = df2.drop_duplicates('Mobile_Number').set_index('Mobile_Number')['Occur_Date']
s2 = df1['Mobile_Number'].map(s1)

m = s2.between(df1['Book_Date'], df1['App_Date'])

#solution with no mask
df1['Difference1'] = df1['App_Date'].sub(s2).dt.days
#solution with test between
df1['Difference2'] = np.where(m, df1['App_Date'].sub(s2).dt.days, np.nan)
print (df1)
   Mobile_Number  Book_Date   App_Date Difference  Difference1  Difference2
0      503477334 2018-10-12 2018-10-18 2018-10-16          2.0          2.0
1      506002884 2018-10-12 2018-10-19 2018-10-21         -2.0          NaN
2      501022162 2018-10-12 2018-10-16 2018-10-15          1.0          1.0
3      503487338 2018-10-13 2018-10-13 2018-10-13          0.0          0.0
4      506012887 2018-10-13 2018-10-21 2018-10-14          7.0          7.0
5      503427339 2018-10-14 2018-10-17        NaT          NaN          NaN

编辑:

您可以使用merge 代替map 来连接两列:

df1['Book_Date'] = pd.to_datetime(df1['Book_Date'])
df1['App_Date'] = pd.to_datetime(df1['App_Date'])
df2['Occur_Date'] = pd.to_datetime(df2['Occur_Date'])

df3 = df1.merge(df2, on=['Category','Mobile_Number'], how='left')
print (df3)
  Category  Mobile_Number  Book_Date   App_Date Occur_Date
0        A      503477334 2018-10-12 2018-10-18 2018-10-16
1        B      503477334 2018-10-07 2018-10-16 2018-10-13
2        C      501022162 2018-10-12 2018-10-16        NaT
3        A      503487338 2018-10-13 2018-10-13 2018-10-13
4        C      506012887 2018-10-13 2018-10-21 2018-10-14
5        E      503427339 2018-10-14 2018-10-17        NaT

m = df3['Occur_Date'].between(df3['Book_Date'], df3['App_Date'])
#print (m)

df3['Difference2'] = np.where(m, df3['App_Date'].sub(df3['Occur_Date']).dt.days, np.nan)
print (df3)
  Category  Mobile_Number  Book_Date   App_Date Occur_Date  Difference2
0        A      503477334 2018-10-12 2018-10-18 2018-10-16          2.0
1        B      503477334 2018-10-07 2018-10-16 2018-10-13          3.0
2        C      501022162 2018-10-12 2018-10-16        NaT          NaN
3        A      503487338 2018-10-13 2018-10-13 2018-10-13          0.0
4        C      506012887 2018-10-13 2018-10-21 2018-10-14          7.0
5        E      503427339 2018-10-14 2018-10-17        NaT          NaN

【讨论】:

  • 那行得通:D 你是数据争吵的野兽!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-15
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 2017-02-03
  • 1970-01-01
  • 2021-09-18
相关资源
最近更新 更多