python积累--pandas读取数据积累--dataframe⽤法
通过带有标签的列和索引,Pandas 使我们可以以⼀种所有⼈都能理解的⽅式来处理数据。它可以让我们毫不费⼒地从诸如 csv 类型的⽂件中导⼊数据。我们可以⽤它快速地对数据进⾏复杂的转换和过滤等操作。
pandas和 Numpy、Matplotlib ⼀起构成了⼀个 Python 数据探索和分析的强⼤基础。Scipy是同类型的库,感兴趣的可以进⾏了解。
本⽂记录和收集积累pandas的⽤法。
导⼊ Pandas
import pandas as pd # This is the standard
这是导⼊ pandas 的标准⽅法。我们不想⼀直写 pandas 的全名,但是保证代码的简洁和避免命名冲突都很重要,所以折中使⽤ pd 。如果你去看别⼈使⽤ pandas 的代码,就会看到这种导⼊⽅式。
Pandas 中的数据类型
Pandas 基于两种数据类型,series 和 dataframe。
series 是⼀种⼀维的数据类型,其中的每个元素都有各⾃的标签。你可以把它当作⼀个由带标签的元素组成的 numpy 数组。标签可以是数字或者字符。 通俗的理解就是 带有标签的⾏ 或者带有标签的列。
dataframe 是⼀个⼆维的、表格型的数据结构。Pandas 的 dataframe 可以储存许多不同类型的数据,并且每个轴都有标签。你可以把它当作⼀个 series 的字典。通俗的理解就是 ⾏列带有标签的表格。
将数据导⼊ Pandas
# Reading a csv into Pandas.
df = pd.read_csv('my_data.csv', header=0)
如果你的数据集中有中⽂的话,最好在⾥⾯加上 encoding = ‘gbk’ ,以避免乱码问题。后⾯的导出数据的时候也⼀样。
这⾥我们从 csv ⽂件⾥导⼊了数据,并储存在 dataframe 中。这⼀步⾮常简单,你只需要调⽤ read_csv 然后将⽂件的路径传进去就⾏了。header 关键字告诉 Pandas 哪些是数据的列名。如果没有列名的话就将它设定为 None 。
查看前 x ⾏的数据
# Getting first x rows.
df.head(5)
我们只需要调⽤ head() 函数并且将想要查看的⾏数传⼊。
查看某列所有的值
df[column].unique()
查看后 x ⾏的数据
# Getting last x rows.
df.tail(5)
跟 head ⼀样,我们只需要调⽤ tail 并且传⼊想要查看的⾏数即可。注意,它并不是从最后⼀⾏倒着显⽰的,⽽是按照数据原来的顺序显⽰。
修改列名
输⼊新列名即可
# Changing column labels.
'rain_decfeb', 'outflow_decfeb', 'rain_junaug', 'outflow_junaug']
选取指定的列
final_result= tree_have_mbarcode_wbarcode_manwife_wifeman[['r_id','source','man','wife','relation']]
查询总⾏数
在 Pandas 中,⼀条记录对应着⼀⾏,所以我们可以对数据集调⽤ len ⽅法,它将返回数据集的总⾏数:
# Finding out how many rows dataset has.
len(df)
上⾯的代码返回⼀个表⽰数据⾏数的整数
统计表格
你可能还想知道数据集的⼀些基本的统计数据,在 Pandas 中,这个操作简单到哭:
# Finding out basic statistical information on your dataset.
pd.options.display.float_format = '{:,.3f}'.format # Limit output to 3 decimal places.
df.describe()
这将返回⼀张表,其中有诸如总数、均值、标准差之类的统计数据:
提取⼀整列
使⽤列的标签可以⾮常简单地做到:
# Getting a column by label
df['rain_octsep']
注意,当我们提取列的时候,会得到⼀个 series ,⽽不是 dataframe 。记得我们前⾯提到过,你可以把 dataframe 看作是⼀个 series 的字典,所以在抽取列的时候,我们就会得到⼀个 series。
使⽤点号获取列
访问对象属性⼀样访问数据集的列——只⽤⼀个点号。
# Getting a column by label using .
df.rain_octsep
这句代码返回的结果与前⼀个例⼦完全⼀样——是我们选择的那列数据。
返回列是否符合条件
pandas可以使⽤布尔过滤(boolean masking)的技术,通过在⼀个数组上运⾏条件来得到⼀个布林数组。
# Creating a series of booleans based on a conditional
df.rain_octsep < 1000 # Or df['rain_octsep] < 1000
上⾯的代码将会返回⼀个由布尔值构成的 dataframe。True 表⽰在⼗⽉-九⽉降⾬量⼩于 1000 mm,False 表⽰⼤于等于 1000 mm。我们可以⽤这些条件表达式来过滤现有的 dataframe。
筛选符合条件的列
# Using a series of booleans to filter
df[df.rain_octsep < 1000]
这条代码只返回⼗⽉-九⽉降⾬量⼩于 1000 mm 的记录:
也可以通过复合条件表达式来进⾏过滤:
# Filtering by multiple conditionals
df[(df.rain_octsep < 1000) & (df.outflow_octsep < 4000)] # Can't use the keyword 'and'
这条代码只会返回 rain_octsep 中⼩于 1000 的和 outflow_octsep 中⼩于 4000 的记录:
注意重要的⼀点:这⾥不能⽤ and 关键字,因为会引发操作顺序的问题。必须⽤ & 和圆括号。
和操作 使⽤&、或操作使⽤|、not操作使⽤ ~
df = df[(df['user:Name'].str.find('condor')>=0) | (df['UsageType'].str.find('CNW1-SpotUsage:c4.8xlarge')>=0)]
列筛选–字符串匹配–包含等
如果你的数据是字符串,你也可以使⽤字符串⽅法来进⾏过滤:
# Filtering by string methods
df[df.water_year.str.startswith('199')]
注意,你必须⽤ .str.[string method] ,⽽不能直接在字符串上调⽤字符⽅法。上⾯的代码返回所有 90 年代的记录。
⾏选择的前提—设置索引
可以设置⼀个(或者多个)新的索引:
# Setting a new index from an existing column
df = df.set_index(['water_year'])
df.head(5)
上⾯的代码将 water_year 列设置为索引。注意,列的名字实际上是⼀个列表,虽然上⾯的例⼦中只有⼀个元素。如果你想设置多个索引,只需要在列表中加⼊列的名字即可。
数字型的标签–⾏选择–iloc
之前的部分展⽰了如何通过列操作来得到数据,但是 Pandas 的⾏也有标签。⾏标签可以是基于数字的或者是标签,⽽且获取⾏数据的⽅法也根据标签的类型各有不同。
如果你的⾏标签是数字型的,你可以通过 iloc 来引⽤:
# Getting a row via a numerical index
df.iloc[30]
iloc 只对数字型的标签有⽤。它会返回给定⾏的 series,⾏中的每⼀列都是返回 series 的⼀个元素。
字符型的标签–⾏选择–loc
我们设置的索引列中都是字符型数据,这意味着我们不能继续使⽤ iloc 来引⽤,那我们⽤什么呢?⽤ loc 。
# Getting a row via a label-based index
df.loc['2000/01']
和 iloc ⼀样,loc 会返回你查询的⾏,唯⼀⼀点不同就是此时你使⽤的是基于字符串的引⽤,⽽不是基于数字的。
字符型和数字类型的标签–⾏选择–ix
还有⼀个引⽤列的常⽤常⽤⽅法—— ix 。如果 loc 是基于标签的,⽽ iloc 是基于数字的,那 ix 是基于什么的?事实上,ix 是基于标签的查询⽅法,但它同时也⽀持数字型索引作为备选。
# Getting a row via a label-based or numerical index
df.ix['1999/00'] # Label based with numerical index fallback *Not recommended
与 iloc、loc ⼀样,它也会返回你查询的⾏。
如果 ix 可以同时起到 loc 和 iloc 的作⽤,那为什么还要⽤后两个?⼀⼤原因就是 ix 具有轻微的不可预测性。还记得我说过它所⽀持的数字型索引只是备选吗?这⼀特性可能会导致 ix 产⽣⼀些奇怪的结果,⽐如讲⼀个数字解释为⼀个位置。⽽使⽤ iloc 和 loc 会很安全、可预测并且让⼈放⼼。但是我要指出的是,ix ⽐ iloc 和 loc 要快⼀些。
选取等于某些值的⾏记录
⽤ ==
df.loc[df['column_name'] == some_value]
选取某列是否需要的数值⽤ isin
df.loc[df['column_name'].isin(some_values)]
多种条件的选取⽤ &
df.loc[(df['column'] == some_value) & df['other_column'].isin(some_values)]
选取不等于某些值的⾏记录⽤!=
df.loc[df['column_name'] != some_value]
isin返回⼀系列的数值,如果要选择不符合这个条件的数值使⽤~ df.loc[~df['column_name'].isin(some_values)]
按位置选择
通过传递的整数的位置进⾏选择:
df.iloc[3] #取出第三⾏
Clipboard Image.png
通过整数切⽚,类似于numpy / python:
df.iloc[3:5,0:2]
Clipboard Image.png
切出3-4⾏,1-2列⼀块区域
通过整数位置列表切分,类似numpy的/ Python的风格:
df.iloc[[1,2,4],[0,2]]
切分出某些⾏:
df.iloc[1:3,:]
切分出某些列:
df.iloc[:,1:3]
获取某个值
df.iloc[1,1]
快速访问某个值(等同于先前的⽅法):
df.iat[1,1]
⼀个dataframe拆分成多个
df = pd.read_csv('data/tgnb_merge.csv', encoding='utf-8')
# df.drop_duplicates(keep='first', inplace=True)  # 去重,只保留第⼀次出现的样本
df = df.sample(frac=1.0)  # 全部打乱
cut_idx = int(round(0.1 * df.shape[0]))
df_test, df_train = df.iloc[:cut_idx], df.iloc[cut_idx:]
print df.shape, df_test.shape, df_train.shape  # (3184, 12) (318, 12) (2866, 12)
合并连接多个dataframe
df1=DataFrame(np.random.randn(3,4),columns=['a','b','c','d'])
df2=DataFrame(np.random.randn(2,3),columns=['b','d','a'])
a        b        c        d
0 -0.848557 -1.163877 -0.306148 -1.163944
1  1.358759  1.159369 -0.532110  2.183934
2  0.532117  0.788350  0.703752 -2.620643
0 -0.316156 -0.707832      NaN -0.416589
1  0.406830  1.34593
2      NaN -1.874817
a        b        c        dpython新手代码userid
0 -0.848557 -1.163877 -0.306148 -1.163944
1  1.358759  1.159369 -0.532110  2.183934
2  0.532117  0.788350  0.703752 -2.620643
3 -0.316156 -0.707832      NaN -0.416589
4  0.406830  1.345932      NaN -1.874817
排序去重取第⼀条数据
df_user = df_user.sort_values(['#account_id'],ascending=False)
df_user_distinct = upby(['#account_id']).head(1)
根据多列分组,对其中⼀列进⾏统计
根据A、B列分组,对C列进⾏求和:
upby(['A','B'])[['C']].sum()
根据A、B列分组,对C列进⾏计数:
upby(['A','B'])[['C']].count()
根据某列分组后,拼接字符串列
order_info['productname'] = upby(['userid_db_order'])['productname'].transform(lambda x : ' '.join(x)) order_info = order_info.drop_duplicates()
print(order_info)
索引排序
将索引排序通常会很有⽤,在 Pandas 中,我们可以对 dataframe 调⽤ sort_index ⽅法进⾏排序。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。