我有一个大的txt文件(~300 mb),其值和形状如下:
df= pd.read_csv('file.txt')
df.head()
<Base> <DTYYYYMMDD> <TIME> <p1> <p2> <p3> <p4> <q>
36 x 20010102 235700 0.5622 0.5622 0.5622 0.5622 4
37 x 20010102 235800 0.5622 0.5622 0.5622 0.5622 4
38 x 20010102 235900 0.5622 0.5622 0.5622 0.5622 4
39 x 20010103 0 0.5618 0.5618 0.5618 0.5618 4
40 x 20010103 300 0.5622 0.5622 0.5622 0.5622 4
41 x 20010103 500 0.5622 0.5622 0.5622 0.5622 4
df.shape()
(5560000, 8)
我试图获得值p4并绘制每年出现的次数等等。为此,我试图首先将DTYYYYMMDD和TIME字段转换为字符串(它们从文本文件中读取为整数),然后将它们转换为datetime,如下所示:
datestr = df['<DTYYYYMMDD>'].apply(lambda x: str(x))
timestr = df['<TIME>'].apply(lambda x: str(x))
zeros = timestr.apply(lambda x: '0' * (6- len(x)))
timestr = zeros + timestr
dtstr = datestr + timestr
p4_df = df['<p4>']
dt_datetime = pd.to_datetime(dtstr, format = '%Y%m%d%H%M%S')
p4_df.index = dt_datetime
现在我试图单独获取日期部分,以便我可以将其分组并计算出现次数。我需要保留完整的日期时间索引,因为我在其他计算中需要它。
p4_df['Date'] = dt_datetime.apply(lambda x: x.date())
to_plot = p4_df.groupby(['Date'])['<p4>'].count()
to_plot.plot()
我在dt_datetime.apply
行遇到内存错误。我尝试使用以下代码,但仍然是错误:
p4_df['Date'] = pd.to_datetime(datestr, format = '%Y%m%d')
有什么建议可以让代码更节省内存吗?
答案 0 :(得分:1)
您需要astype
才能转换为字符串,然后按zfill
添加零:
dtstr = df['<DTYYYYMMDD>'].astype(str) + df['<TIME>'].astype(str).str.zfill(6)
df.index = pd.to_datetime(dtstr, format = '%Y%m%d%H%M%S')
print (df)
<Base> <DTYYYYMMDD> <TIME> <p1> <p2> <p3> \
2001-01-02 23:57:00 x 20010102 235700 0.5622 0.5622 0.5622
2001-01-02 23:58:00 x 20010102 235800 0.5622 0.5622 0.5622
2001-01-02 23:59:00 x 20010102 235900 0.5622 0.5622 0.5622
2001-01-03 00:00:00 x 20010103 0 0.5618 0.5618 0.5618
2001-01-03 00:03:00 x 20010103 300 0.5622 0.5622 0.5622
2001-01-03 00:05:00 x 20010103 500 0.5622 0.5622 0.5622
<p4> <q>
2001-01-02 23:57:00 0.5622 4
2001-01-02 23:58:00 0.5622 4
2001-01-02 23:59:00 0.5622 4
2001-01-03 00:00:00 0.5618 4
2001-01-03 00:03:00 0.5622 4
2001-01-03 00:05:00 0.5622 4
如果dates
使用DatetimeIndex.floor
,则会获得更好的效果:
#if dont need omit NaNs use size instaed count
to_plot = df.groupby(df.index.floor('D'))['<p4>'].count()
to_plot.plot()
或使用date
:
to_plot = df.groupby(df.index.date)['<p4>'].count()
to_plot.plot()
另一个想法是仅使用<DTYYYYMMDD>
,然后无需转换为string
:
df.index = pd.to_datetime(df['<DTYYYYMMDD>'], format = '%Y%m%d')
print (df)
<Base> <DTYYYYMMDD> <TIME> <p1> <p2> <p3> <p4> <q>
<DTYYYYMMDD>
2001-01-02 x 20010102 235700 0.5622 0.5622 0.5622 0.5622 4
2001-01-02 x 20010102 235800 0.5622 0.5622 0.5622 0.5622 4
2001-01-02 x 20010102 235900 0.5622 0.5622 0.5622 0.5622 4
2001-01-03 x 20010103 0 0.5618 0.5618 0.5618 0.5618 4
2001-01-03 x 20010103 300 0.5622 0.5622 0.5622 0.5622 4
2001-01-03 x 20010103 500 0.5622 0.5622 0.5622 0.5622 4
to_plot = df.groupby(level=0)['<p4>'].count()
print (to_plot)
<DTYYYYMMDD>
2001-01-02 3
2001-01-03 3
Name: <p4>, dtype: int64
EDIT1:应该首先按字符串聚合然后转换为datetime较小的聚合输出来提高性能:
to_plot = df.groupby('<DTYYYYMMDD>')['<p4>'].count()
to_plot.index = pd.to_datetime(to_plot.index, format = '%Y%m%d')
print (to_plot)
<DTYYYYMMDD>
2001-01-02 3
2001-01-03 3
Name: <p4>, dtype: int64
EDIT2:
如果需要在另一个代码中使用变量:
datestr = df['<DTYYYYMMDD>'].astype(str)
timestr = df['<TIME>'].astype(str).str.zfill(6)
dtstr = datestr + timestr
p4_df = df['<p4>']
dt_datetime = pd.to_datetime(dtstr, format = '%Y%m%d%H%M%S')
p4_df.index = dt_datetime
p4_df['Date'] = dt_datetime.date()
to_plot = p4_df.groupby(['Date'])['<p4>'].count()
to_plot.plot()
答案 1 :(得分:0)
我也发生了同样的事情,因为groupby /占用了太多内存,并且我们遇到了Out of Memory错误。诀窍是要按日期/月份/年份进行操作,而不要按完整的日期进行操作,因此操作就像是一种魅力。
df['Date'] = pd.to_datetime(df["<DTYYYYMMDD>"], format = '%Y%m%d') ## convert to datetime format
df['Year'] = df.Date.dt.year ## can use month / date
to_plot = df.groupby('Year')['Year'].count()
to_plot.plot()
如果您在不同的列上有年/月,请使用
df.groupby(['Year','Month']['Month'].count()
按年/月/日进行操作要快得多。无需转换为字符串!