我有一个大的(3MM记录(文件。
该文件包含四列:[id,startdate,enddate,status]每个id都会有多个状态更改,我的目标是转换这些数据,最终得到一个包含以下列的宽数据帧:
[id, status1, status2, status3... statusN]
其中,行的值将是id,列的状态的开始日期。
一行的例子是:
["xyz", '2020-08-24 23:42:54', '(blank)', '2020-08-26 21:23:45'...(startdate value for status N)]
我写了一个脚本,它可以执行以下操作:遍历第一个数据帧的所有行,并将状态存储在一个集合中,这样就不会有重复,我可以获得所有状态的足够列表。
df = pd.read_csv('statusdata.csv')
columns = set()
columns.add('id')
for index, row in df.iterrows():
columns.add(row['status'])
然后,我创建了一个新的数据帧,列为"id",然后从Set 中获取所有其他状态
columnslist = list(columns)
newdf = pd.DataFrame(columns = columnslist)
newdf = newdf[['id']+[c for c in newdf if c not in ['id']]] #this will make 'id' the first column
然后,我遍历原始数据帧的所有列,如果它读取的id不在数据帧中,则在新数据帧中创建一个新记录,然后将原始df中指示的状态的开始日期记录在新df中的匹配列上。
for index, row in df.iterrows():
if row['opportunityid'] not in newdf['id']:
newdf.loc[len(newdf), 'id'] = row['opportunityid']
newdf.loc[newdf['id'] == row['opportunityid'], row['status']] = row['startdate']
我关心的是代码的速度。按照这个速度,将需要13个多小时才能通过原始数据帧的所有行,将其转换为具有唯一密钥的新数据帧。有没有办法提高效率?有没有办法从我的电脑中分配更多的内存?或者有没有办法在aws或其他云计算软件上部署这些代码,使其运行更快?我目前正在一台带有32GB ram的2020款13英寸mac book pro上运行此软件。
谢谢!
IIUC,您可以在不迭代的情况下完成此操作。首先,创建样本数据:
from io import StringIO
import pandas as
data = '''id, start, end, status
A, 1, 10, X
A, 2, 20, Y
A, 3, 30, Z
A, 9, 99, Z
B, 4, 40, W
B, 5, 50, X
B, 6, 60, Y
'''
df = pd.read_csv(StringIO(data), sep=', ', engine='python')
print(df)
id start end status
0 A 1 10 X
1 A 2 20 Y
2 A 3 30 Z
3 A 9 99 Z # <- same id + status as previous row
4 B 4 40 W
5 B 5 50 X
6 B 6 60 Y
其次,选择感兴趣的列(除了end
之外的所有列(;将CCD_ 2和CCD_;squeeze()
,以确保对象被转换为熊猫系列;最后将CCD_ 5作为列标签:
t = (df[['id', 'start', 'status']]
.groupby(['id','status'], as_index=False)['start'].max() # <- new
.set_index(['id', 'status'], verify_integrity=True)
.sort_index()
.squeeze()
.unstack(level='status')
)
print(t)
status W X Y Z
id
A NaN 1.0 2.0 9.0
B 4.0 5.0 6.0 NaN
NaN值显示了当status
中没有100%重叠时发生的情况。
更新
我添加了一行数据以导致(id,status(对重复。还添加了groupby()
方法来提取最新的(id,status(对。