按年份分组csv字符串

时间:2016-03-18 11:01:48

标签: python parsing csv datetime pandas

我需要获得2014年和2015年的数据。 我怎么能这样做如果我有一个字符串文件(有499千)

4be390eefaf9a64e7cb52937c4a5c77a,"e1.ru",2014-09-30 18:14:58,57,4
4be390eefaf9a64e7cb52937c4a5c77a,"e1.ru",2014-09-30 20:11:15,1884,90
4be390eefaf9a64e7cb52937c4a5c77a,"e1.ru",2014-10-04 09:44:21,1146,6
4be390eefaf9a64e7cb52937c4a5c77a,"avito.ru",2014-09-29 21:01:29,48,3

我尝试转换日期格式d = datetime.strptime('used_at', "%Y-%m-%d %H:%M:%S"),但我遇到了错误:时间数据' used_at'不符合格式'%Y-%m-%d%H:%M:%S'。

我试过df.groupby(df['date_col'].dt.year) 但有一个错误只能使用.dt访问器与datetimelike值 我读了csv infile = pd.read_csv("avito_trend.csv")

2 个答案:

答案 0 :(得分:2)

你似乎没有做我们要求的事情,所以这里有一些代码证明如果你按照我的要求行事:

In [11]:
import io
import pandas as pd
t="""4be390eefaf9a64e7cb52937c4a5c77a,"e1.ru",2014-09-30 18:14:58,57,4
4be390eefaf9a64e7cb52937c4a5c77a,"e1.ru",2014-09-30 20:11:15,1884,90
4be390eefaf9a64e7cb52937c4a5c77a,"e1.ru",2014-10-04 09:44:21,1146,6
4be390eefaf9a64e7cb52937c4a5c77a,"avito.ru",2014-09-29 21:01:29,48,3"""
df = pd.read_csv(io.StringIO(t), header=None, parse_dates=[2])
df.info()

<class 'pandas.core.frame.DataFrame'>
Int64Index: 4 entries, 0 to 3
Data columns (total 5 columns):
0    4 non-null object
1    4 non-null object
2    4 non-null datetime64[ns]
3    4 non-null int64
4    4 non-null int64
dtypes: datetime64[ns](1), int64(2), object(2)
memory usage: 192.0+ bytes

您可以从上面看到第3列的dtype现在是datetime64,然后您可以使用dt.year访问年份组件,groupby就可以:

In [14]:    
df.groupby(df[2].dt.year).first()

Out[14]:
                                     0      1                   2   3  4
2                                                                       
2014  4be390eefaf9a64e7cb52937c4a5c77a  e1.ru 2014-09-30 18:14:58  57  4

您可以选择使用此属性进行过滤或屏蔽:

In [15]:
df[2].dt.year

Out[15]:
0    2014
1    2014
2    2014
3    2014
Name: 2, dtype: int64

您可以使用isin e.t.c将上述内容与标量值或成员资格测试进行比较。

你尝试了什么:

datetime.strptime('used_at', "%Y-%m-%d %H:%M:%S")

无意义strptime接受日期时间字符串,您可能想要传递列:

datetime.strptime(df['used_at'], "%Y-%m-%d %H:%M:%S")

但是这会失败,因为strptime接受标量值,而不是大熊猫系列。

如果你df['used_at'].apply(lambda x: datetime.strptime(x, "%Y-%m-%d %H:%M:%S"))那么它会起作用,但这很慢,你可以使用to_datetime来获得相同的结果,但这是矢量化的:

pd.to_datetime(df['used_at'])

答案 1 :(得分:1)

您可以按dt.yearisin选择年份为20142015的行:

import pandas as pd
import io

temp=u"""4be390eefaf9a64e7cb52937c4a5c77a,"e1.ru",2013-09-30 18:14:58,57,4
4be390eefaf9a64e7cb52937c4a5c77a,"e1.ru",2014-09-30 20:11:15,1884,90
4be390eefaf9a64e7cb52937c4a5c77a,"e1.ru",2015-10-04 09:44:21,1146,6
4be390eefaf9a64e7cb52937c4a5c77a,"avito.ru",2016-09-29 21:01:29,48,3"""

df = pd.read_csv(io.StringIO(temp), #after testing replace io.StringIO(temp) to filename
                 header=None, #no header
                 parse_dates=[2], #parse 3rd column to datetime
                 names=['a', 'url', 'used_at', 'b', 'c']) #set columns names

print df
                                  a       url             used_at     b   c
0  4be390eefaf9a64e7cb52937c4a5c77a     e1.ru 2013-09-30 18:14:58    57   4
1  4be390eefaf9a64e7cb52937c4a5c77a     e1.ru 2014-09-30 20:11:15  1884  90
2  4be390eefaf9a64e7cb52937c4a5c77a     e1.ru 2015-10-04 09:44:21  1146   6
3  4be390eefaf9a64e7cb52937c4a5c77a  avito.ru 2016-09-29 21:01:29    48   3

#create boolean mask, which rows contain years 2014 or 2015
print df['used_at'].dt.year.isin([2014,2015])
0    False
1     True
2     True
3    False
Name: used_at, dtype: bool

#filter dataframe by mask
print df[ df['used_at'].dt.year.isin([2014,2015])]
                                  a    url             used_at     b   c
1  4be390eefaf9a64e7cb52937c4a5c77a  e1.ru 2014-09-30 20:11:15  1884  90
2  4be390eefaf9a64e7cb52937c4a5c77a  e1.ru 2015-10-04 09:44:21  1146   6

编辑:

列名称位于csv header,因此您可以省略它们:

import pandas as pd

infile = pd.read_csv("avito_trend.csv", 
                      parse_dates=[2])

print infile

print infile[ infile['used_at'].dt.year.isin([2014,2015])]