Python-将同一天(日期)拆分为多列



我使用的是panda,我有一列考勤时间戳数据(Date(。我想将当天的值拆分为(InTime(和(OutTime(列。

df = df[['Date']]
Date
Thu 1/09 9:10 AM
Thu 1/09 6:10 PM
Fri 2/09 9:04 AM
Fri 2/09 6:02 PM

我正在努力达到以下结果。

In Time            OutTime
Thu 1/09 9:10 AM   Thu 1/09 6:10 PM 
Fri 2/09 9:04 AM   Fri 2/09 6:02 PM

谢谢。

编辑

谢谢你的帮助。问题是数据没有达到应有的整洁程度。缺少In-Time/Out-Time或接近重复的记录。+我是一个基本的python用户,我甚至无法理解根据我的需求修改它的代码。

我请求查看完整的场景,以及我迄今为止为实现预期结果所做的尝试。

这是一个考勤机数据,用户要么忘记标记考勤,要么机器创建了一个重复条目以获得更长的拇指印象。因此,所提供的代码将AM和PM列混淆在一起,只要它发现任何重复或丢失的记录。

样本数据看起来像这个

User    Date
11  Thu 1/09 9:10 AM
3   Thu 1/09 9:10 AM
4   Thu 1/09 9:10 AM
2   Thu 1/09 9:23 AM
5   Thu 1/09 9:39 AM    
... ...   ...
12  Fri 30/09 5:55 PM
5   Fri 30/09 6:01 PM
6   Fri 30/09 6:04 PM
11  Fri 30/09 6:09 PM

我正在尝试为每个用户创建多个.csv文件,其中"输入"one_answers"输出"时间戳位于单独的列中,包括非连续天的空记录,以便将其粘贴到已创建的Excel模板中。

df = pd.read_csv('input.csv', encoding="utf-8", sep=',')
df = df[["User", "Date"]]
dataframe = pd.DataFrame(df,
columns=['User', 'Date'])
users = {
'falcon': 2,
'charlie': 3,
}
for username, ID in users.items():
df = dataframe.loc[dataframe['User'] == ID]
df = df[['Date']]
df.to_csv(username + ".csv", encoding="utf-8", sep=',', header=False, index=False)

结果

Thu 1/09 9:10 AM
Thu 1/09 6:11 PM
Fri 2/09 9:18 AM    //Missing PM
Sat 3/09 10:44 AM
Sat 3/09 6:00 PM
Mon 5/09 9:22 AM    //Missing PM
Tue 6/09 9:09 AM
Tue 6/09 6:25 PM
Wed 7/09 9:18 AM
Wed 7/09 6:33 PM

我试图将这些日期分开,这样带有AM/PM的条目就可以在其相应的列中分开(包括缺少日期的空记录(。

以下是一个包含pandas.DataFrame.joinpandas.DataFrame.shift的解决方案:

new_df = (
df.add_suffix('_In_time')
.join(df.shift(-1).add_suffix('_Out_time'))
.iloc[::2]
)

#输出:

print(new_df)
Date_In_time     Date_Out_time
0  Thu 1/09 9:10 AM  Thu 1/09 6:10 PM
1  Fri 2/09 9:04 AM  Fri 2/09 6:02 AM

代码

注意:这段代码是在考虑原始帖子的情况下编写的(请参阅下面的更新部分(

import pandas as pd
from io import StringIO
from dateutil.parser import parse
data = '''User,Date
1,Thu 1/09 9:10 AM
1,Thu 1/09 6:11 PM
1,Fri 2/09 9:18 AM
1,Sat 3/09 10:44 AM
1,Sat 3/09 6:00 PM
1,Mon 5/09 9:22 AM
1,Tue 6/09 9:09 AM
1,Tue 6/09 6:25 PM
1,Wed 7/09 9:18 AM
1,Wed 7/09 6:33 PM
2,Thu 1/09 9:13 AM
2,Thu 1/09 6:10 PM
2,Fri 2/09 9:10 AM
2,Fri 2/09 6:10 PM
2,Sat 3/09 10:40 AM
2,Sat 3/09 5:55 PM
2,Tue 6/09 6:21 PM
2,Wed 7/09 9:10 AM
2,Wed 7/09 6:30 PM
'''
df = pd.read_csv(
StringIO(data), 
parse_dates=[1], 
date_parser=lambda x: parse(x, dayfirst=True)
)
df['Day'] = df['Date'].dt.date
df['InOut'] = df['Date'].dt.strftime('%p').map({'AM':'In time', 'PM':'Out time'})
output = df.pivot(index=['User','Day'], columns='InOut',values='Date')
users = df['User'].unique()
days = pd.date_range(start=df['Day'].min(), end=df['Day'].max(), freq='D')
index = pd.MultiIndex.from_product([users, days])
output = output.reindex(index, fill_value=pd.NA)
for user_id, group in output.groupby(level=0):
group.to_csv(
f'user_{user_id}.csv', 
index=False, 
date_format='%a %d/%m %I:%M %p'
)

备注

假设我们有一些csv格式的数据:

用户日期425/9周一上午10:50

查看您共享的csv,很明显日期格式存在问题(不一致,但目前不是问题(和重复条目。

请注意,有些行缺少AM时间,有些行则缺少PM时间。假设一个用户早上进,下午出,我做了一个简单的循环,检查每个用户的进和出时间,并加上";缺少";以防条目丢失。为每个用户生成一个数据帧,然后连接所有数据帧。如果需要,可以对最终的数据帧进行排序,但必须首先对数据格式进行标准化。我没有做这一步,因为这不是问题的一部分,没有它问题可以解决

import pandas as pd
input_csv = '/Users/alec/Downloads/python-split-dates-data/sandbox.csv'
df = pd.read_csv(input_csv)
print(df)
User              Date
0      11  Sun 9/01 9:10 AM
1       3  Sun 9/01 9:10 AM
2       4  Sun 9/01 9:10 AM
3       2  Sun 9/01 9:23 AM
4       5  Sun 9/01 9:39 AM
..    ...               ...
339    12   9/30/22 5:55 PM
340     5   9/30/22 6:01 PM
341     6   9/30/22 6:04 PM
342    11   9/30/22 6:09 PM
343     4   9/30/22 6:19 PM
[344 rows x 2 columns]

cleaned_df = []
for user, group in df.drop_duplicates().groupby('User'):
am = [] #store AM entries
pm = [] #store PM entries
for i, row in group.iterrows():
if row.Date.endswith('AM'):
am.append(row.Date)
elif row.Date.endswith('PM'):
while len(am) <= len(pm):
am.append('missing IN') #add missing
while len(pm) < len(am)-1:
pm.append('missing OUT') #add missing
pm.append(row.Date)
assert len(am) == len(pm) #double check data is consistent
_df = pd.DataFrame({'User':[user]*len(am), 'IN':am, 'OUT':pm})
cleaned_df.append(_df)

new_df = pd.concat(cleaned_df)
print(new_df)
User                IN               OUT
0      2  Sun 9/01 9:23 AM  Sun 9/01 5:55 PM
1      2  Wed 9/02 9:20 AM  Wed 9/02 5:46 PM
2      2  Wed 9/03 9:24 AM  Wed 9/03 5:46 PM
3      2  Mon 9/05 9:23 AM  Mon 9/05 5:40 PM
4      2  Thu 9/06 9:26 AM  Thu 9/06 5:49 PM
..   ...               ...               ...
0     12        missing IN   9/23/22 5:54 PM
1     12  9/27/22 10:24 AM   9/27/22 1:34 PM
2     12   9/28/22 9:01 AM   9/28/22 5:51 PM
3     12   9/29/22 9:08 AM   9/29/22 5:52 PM
4     12   9/30/22 9:16 AM   9/30/22 5:55 PM
[182 rows x 3 columns]

另一种方法,将列转换为datetime并使用它。尝试:

df
Date
0   Thu 1/09 9:10 AM
1   Thu 1/09 6:10 PM
2   Fri 2/09 9:04 AM
3   Fri 2/09 6:02 PM
df['Date'] = pd.to_datetime(df['Date'] + ' 2022', format='%a %d/%m %H:%M %p %Y')
df['day'] = df['Date'].dt.date
df['time'] = df['Date'].dt.time
df.groupby('day').agg(InTime=('time', 'first'), OutTime=('time', 'last')).reset_index()
day         InTime      OutTime
0   2022-09-01  09:10:00    06:10:00
1   2022-09-02  09:04:00    06:02:00

基于pandas.DataFrame.pivot:的可能解决方案

# separate day from time
df[['Date1', 'Date2']] = df['Date'].str.split('(?<=d)s(?=d)', expand=True)
# create column with colnames for the new columns to be created by pivot
df['names'] = ['inTime', 'OutTime'] * (len(df)//2)
(df.pivot(index='Date1', columns='names', values='Date')
.reset_index(drop=True).iloc[:,::-1])

输出:

names            inTime           OutTime
0      Fri 2/09 9:04 AM  Fri 2/09 6:02 PM
1      Thu 1/09 9:10 AM  Thu 1/09 6:10 PM

如果数据集没有从早到晚的时间排序,则解决方案可能如下:

# separate day from time
df[['Date1', 'Date2', 'Date3']] = df['Date'].str.split(
'(?<=d)s(?=d)|s(?=.M$)', expand=True)
# this is needed if the times are no sorted in the initial dataset
df = df.sort_values(['Date1', 'Date3', 'Date2'])
# create column with colnames for the new columns to be created by pivot
df['names'] = ['inTime', 'OutTime'] * (len(df)//2)
(df.pivot(index='Date1', columns='names', values='Date')
.reset_index(drop=True).iloc[:,::-1])

完整代码:

import pandas as pd
import numpy as np
from io import StringIO
text = """
Date
Thu 1/09 9:10 AM
Thu 1/09 6:10 PM
Fri 2/09 9:04 AM
Fri 2/09 6:02 PM
"""
df = pd.read_csv(StringIO(text), sep='s{2,}', engine='python')
# separate day from time
df[['Date1', 'Date2']] = df['Date'].str.split('(?<=d)s(?=d)', expand=True)
# create column with colnames for the new columns to be created by pivot
df['names'] = ['inTime', 'OutTime'] * (len(df)//2)
df = (df.pivot(index='Date1', columns='names', values='Date')
.reset_index(drop=True).iloc[:,::-1])
print(df)

相关内容

  • 没有找到相关文章

最新更新