【转载】【总结】pandas方法中的增删改查

在查方法的时候始终有些困扰
发觉可以按照增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)来归纳
pandas方法中的增删改查,打算近期整理下。

最近遇到一个郁闷的问题,就是列名为日期的时候,使用字符串查询列会出现KeyError。
但是你单独取df.columns出来,所得的类型又是str,郁闷死。取出来的是str,但是你用str是无法检索的,类型不对。有空得深究解决下这个问题

初步探索:http://pandas.pydata.org/pandas-docs/stable/indexing.html
时间序列的列名,会不会是使用去除时间分隔符的字符串来获取呢?
df.loc['20130102':'20130104']
这样其实还是不行,indexing中loc方法是取行的方法……真是窘迫
和Spark的DataFrame对比的传送门:【总结】PySpark的DataFrame处理方法:增删改差

python的list结构拷贝:
c = list(a)
深度拷贝(list中嵌套的list也作为单独拷贝,而不是只引用):

import copy
f = copy.deepcopy(a)

参考链接:[Python] 正确复制列表的方法

读(Read):

df = pd.read_csv('weibo_train_data.txt', sep='\t', header=None)  # 当选择列名为None的时候
df = df.rename(columns={0: 'uid',                                          # 实际的列名为数字,而不是字符串
                        1: 'mid',                                          # 使用 '0': 'uid'来改列名是改不了的
                        2: 'time',
                        3: 'forward_count',
                        4: 'comment_count',
                        5: 'like_count',
                        6: 'content'})
2、GroupBy

通常进行groupby操作的时候,都会进行分组。这样index就拥有层级了。如何去掉层级呢?
group_df = df.groupby(['sub_geo', 'family_desc'], as_index=False)
这样就可以了。
如果需要对日期进行按周、按月、按小时等groupby操作,可以使用pd.Grouper(类似于SQL的window函数):

df.groupby([pd.Grouper(key="date", freq="1H"), "Location"]).agg({"Event": np.size, "Cost": np.mean})
3、如果对有层级的数据,要按照某层进行groupby怎么办呢?这样:

df.groupby(df.index.get_level_values(0)).sum()
假设数据是这样:

            col1   col2
ind1 ind2         
A     0       3      2
      1       2      0
      2       2      3
B     3       2      4
C     4       3      1
      5       0      0

那么取出来get_level_values(0)就是指ind1列,而get_level_values(1)是指ind2列。参考
对groupby进行遍历:

for name, df_of_single_group in group_data:
      pass

其中name是一个list,里面包含要groupby的列的数据,df_of_single_group则是一个pandas DataFrame
对其做类型检查则为:

from pandas.core.groupby import DataFrameGroupBy
assert isinstance(group_data, DataFrameGroupBy)
4、读取旋转后的表(转置)

df.T

增(Create):

1、新建一个dataframe:
df2 = pd.DataFrame({'A': 1.,
                    'B': pd.Timestamp('20130102'),
                    'C': pd.Series(1, index=list(range(4)), dtype='float32'),
                    'D': np.array([3] * 4, dtype='int32'),
                    'E': pd.Categorical(["test", "train", "test", "train"]),
                    'F': 'foo'})

或者这样:

import pandas as pd
temp = [[1, 2, 3],
        [4, 5, 6, 6.5],
        [7, 8, 9]]
df_p = pd.DataFrame(temp, columns=['a', 'b', 'c', 'd'])
print(df_p)

————————————————————————————
打印效果:

   a  b  c  d
0  1  2  3 NaN
1  4  5  6 6.5
2  7  8  9 NaN
2、新增一列,是原来列的组合
df['new_col'] = df['a'] + '@' + df['b'] + '@' + df['c']
3、按列归一化(需要借助sklearn包)
from sklearn import preprocessing
df = df.pivot('A', 'B', 'quantity')
x = df.values # returns a numpy array
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
assert isinstance(df, pd.DataFrame)

# 创建df,并将原来的列名封装回去
df = pd.DataFrame(x_scaled, index=df.index.values, columns=df.columns)
4、创建透视表

假设数据是这样的:

    year     month  passengers
0   1949   January     112
1   1949  February     118
2   1949     March     132
3   1949     April     129
…… …… …… ……
11  1949  December     118
12  1950   January     115
13  1950  February     126
14  1950     March     141

我们想转换成列是month,行是year、中间是passengers的数据:

year       1949 1950  1951 1952  1953 1954  1955 1956  1957 1958  1959 
month                                                            
January    112   115   145    171   196  204    242   284   315  340  360  
February   118   126    150   180   196   188    233   277  301  318  342  
March      132    141   178   193    236  235    267   317   356  362  406  
April      129   135   163    181   235  227    269   313   348  348  396  
May        121   125   172   183   229  234    270   318   355  363  420  
June       135   149   178    218   243  264    315   374   422  435  472  
July       148   170    199   230   264   302    364   413  465  491  548  
August     148   170    199   242   272   293    347   405  467  505  559  
September  136   158   184    209   237  259    312   355   404  404  463  
October    119   133   162   191   211  229    274   306   347  359  407  
November   104    114   146  172   180   203    237   271  305  310  362  
December   118    140   166  194    201  229    278   306   336  337  405 

那么可以这样:

import seaborn as sns
flights = sns.load_dataset("flights") # 从seaborn导入样例数据集进行演示
flights = flights.pivot("month", "year", "passengers")

如果行项目需要分更细的级别:

dfp = pd.pivot_table(dfp, index=['date', 'level_row1'], columns='col_item', values='value_col', aggfunc=np.sum)

如果不需要其分层的row,可以这么去除分层:

dfp = dfp.reset_index()
5、字符串的列改成datetime日期格式:
df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d')

删(Delete):

1、删除一列
forecast = forecast.drop(['ds'], axis=1)  # 注意这里的轴axis选择1,意思是删除列。详见这里
2、删除重复数据
df.drop_duplicates()

详见:Pandas标记删除重复记录

3、删除某些行(例:序号删除第0、1行)
df.drop(index=[0, 1])

改(或者叫做更新Update):

所有单元的操作:

1、对表中所有单元作运算(批量更改所有单元):

对DateFrame:

df.apply(lambda x: x + 1)   # 所有格子数值加1

对Series类型也同理:

s.apply(lambda x: x + 1)
2、批量log、e指数运算

批量log运算:

df['y'] = np.log(df['y'])

可用的函数有log10、log2等等,详见这里

批量e指数运算:

df['y'] = df['y'].apply(lambda x: np.e**x)

关于numpy的指数,详见这里

列的操作:

3、改列的内容
date_list = df['date'].tolist() # 可以通过这句获取某一列并返回list类型
…… # 经过一系列操作以后
df['date'] = ['a', 'b', 'c' …… 'z'] # 可以直接把一个list塞进dataframe里面,对该df里的列进行整体更改
4、改列名
df = df.rename(columns={'$a': 'a', '$b': 'b'})
# OR
df.rename(columns={'$a': 'a', '$b': 'b'}, inplace=True)
5、改列名方法二:
a.columns = ['ds', 'y']
6、rename对所有列名的应用lambda表达式:

参考详见这里

df = df.rename(columns=lambda x: x.replace('$', ''))

或者

df.rename(columns=lambda x: x.replace('$', ''), inplace=True)

rename 方法可以获取函数 参考详见这里,例如:

In [11]: df.columns
Out[11]: Index([u'$a', u'$b', u'$c', u'$d', u'$e'], dtype=object)

In [12]: df.rename(columns=lambda x: x[1:], inplace=True)
In [13]: df.columns
Out[13]: Index([u'a', u'b', u'c', u'd', u'e'], dtype=object)

【可以看到,把每列的列名第一个字符之后的字符给选出来了】

7、更改df中列的数据类型:
df_p[['Q', 'R', 'S', 'T']] = df_p[['Q', 'R', 'S', 'T']].astype(np.float32)  # 这么更改会保留除更改列外的其它列
df_p = df_p['Q', 'R', 'S', 'T'].astype(np.float32)  # 这么更改只留下改变类型的列Q、R、S、T

update xx where操作:

8、对某列条件下的所有行的特定列的值更改操作
df_p.loc[df_p['function_name'] == test_func_name, 'state'] = 99

(当function_name这列为test…时,这些行的state列改为99)

9、更改NA的值:
df = df.fillna(value={'sub_geo': 'NA'})

order by操作(sort):

DataFrame.sort_values(by, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last')  

参数说明:

axis:        {0 or ‘index’, 1 or ‘columns’}, default 0,默认按照索引排序,即纵向排序,如果为1,则是横向排序   
by:          str or list of str;如果axis=0,那么by="列名";如果axis=1,那么by="行名";  
ascending:   布尔型,True则升序,可以是[True,False],即第一字段升序,第二个降序  
inplace:     布尔型,是否用排序后的数据框替换现有的数据框  
kind:        排序方法,{‘quicksort’, ‘mergesort’, ‘heapsort’}, default ‘quicksort’。似乎不用太关心  
na_position: {‘first’, ‘last’}, default ‘last’,默认缺失值排在最后面 

查(Search、Retrieve):

选择某列为特定值的所有行:

df = df[df['some_col'] == "abc"]

选择null(nan)的行

df[df['some_col'].isnull()]

选择某几列为其特定值的所有行:

df = df[(df.forward_count > 0) & (df.comment_count > 0) & (df.like_count > 0)]

行选择:

n = fandango[1:3]  # 索引号从0开始,选择了索引号1和2的行数据(不包括3)
o = fandango.loc[1]
p = fandango.loc[1:3]  # 包含了索引号为3的那一行数据
u = fandango.loc[[1,3]] # 索引号从0开始,选择了索引号1和2的行数据(不包括3)

注意:这里loc中塞入的是索引,可以是int、str等等。当删除了某行的时候,索引号(字符串)不会自动调整,因而会出现选错行的情况。如果要严格按照顺序选取,则应当使用iloc。

fandango.iloc[-1]   # 选取DataFrame最后一行,返回的是Series
fandango.iloc[-1:]  # 选取DataFrame最后一行,返回的是DataFrame

列选择:

q = fandango['FILM']
r = fandango[['FILM','Metacritic']]
v = fandango[[0,1,2]]
w = fandango[list(range(5))]  # 注意不能用:的方式,这样x=fandango[[0:5]]是错误的

当我们拿到一个pd.DataFrame如下的时候:

      列名1  列名2  列名3
行名1  内容1  内容2  内容3
行名2  内容4  内容5  内容6
行名3  内容7  内容8  内容9

选择最左侧的index(即获取['行名1', '行名2', '行名3']),并输出成python的list:

df.index.values # 类型为numpy.ndarray,无论是pd.DataFrame还是pd.Series都是这么选择

选择DataFrame中间的数据(即获取['内容1', …… '内容9']不带index与header,输出格式为numpy.ndarray):

df.values  # 类型为numpy.ndarray。无论是pd.DataFrame还是pd.Series都是这么选择

选择header(即获取[‘列名1’, ‘列名2’, ‘列名3’])并输出为python的list:

df.columns —————————————(类型为)—————> pd.Index
df.columns.values ——————(类型为)—————> numpy.ndarray

所有numpy.ndarray类型都可以通过tolist()方法转变成python的list类型。

参考:Pandas之容易让人混淆的行选择和列选择、数据https://github.com/fivethirtyeight/data/tree/master/fandango

单元选择:

str(df['ds'].tail(1).iloc[0])  # 选取ds列末尾最后一个值并转化为str

索引(int行号)获取:

index_num = list(df['fruit']).index("apple")  # 查找fruit列中,元素是apple的那一行的int行号

合并join操作等:
http://blog.csdn.net/ly_ysys629/article/details/73849543

附录(pd.DataFrame中可以映射的数据类型):

Data       type    Description
bool_      Boolean (True or False) stored as a byte
int_       Default integer type (same as C long; normally either int64 or int32)
intc       Identical to C int (normally int32 or int64)
intp       Integer used for indexing (same as C ssize_t; normally either int32 or int64)
int8       Byte (-128 to 127)
int16      Integer (-32768 to 32767)
int32      Integer (-2147483648 to 2147483647)
int64      Integer (-9223372036854775808 to 9223372036854775807)
uint8      Unsigned integer (0 to 255)
uint16     Unsigned integer (0 to 65535)
uint32     Unsigned integer (0 to 4294967295)
uint64     Unsigned integer (0 to 18446744073709551615)
float_     Shorthand for float64.
float16    Half precision float: sign bit, 5 bits exponent, 10 bits mantissa
float32    Single precision float: sign bit, 8 bits exponent, 23 bits mantissa
float64    Double precision float: sign bit, 11 bits exponent, 52 bits mantissa
complex_   Shorthand for complex128.
complex64  Complex number, represented by two 32-bit floats (real and imaginary components)
complex128 Complex number, represented by two 64-bit floats (real and imaginary components)

高阶综合运用,筛选一维表格中按某组重复的列,剩下唯一列并生成二维表:

import pandas as pd
df = pd.DataFrame({
    'a': [3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 6],
    'b': [1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2],
    'c': ['c0', 'c1', 'c2', 'c3', 'c0', 'c1', 'c2', 'c3', 'c0', 'c1', 'c0', 'c1'],
    'd': [7, 6, 7, 7, 7, 7, 7, 8, 5, 9, 5, 9]
})
print('------original df------\n', df)
df2 = pd.pivot_table(df, index=['a', 'b'], columns=['c'])
print(df2)
df4 = df[['b', 'c', 'd']].drop_duplicates(subset=['b', 'c', 'd'])
print('---------drop duplicate to count the num of diff name -----------\n', df4)
df5 = df4.groupby(['b', 'c']).count()
print('-------to find out which val diff twice in group------\n', df5)
filter_column = []
for idx_line in df5[df5['d'] > 1].index:
    print(idx_line, type(idx_line), "<<<<<diff columns>>>>")
    filter_column.append(('d', idx_line[1]))
print("-------Before filter---------")
print(df2)
print("-------After filter---------")
print(df2[filter_column])

输出结果:

------original df------
     a  b   c  d
0   3  1  c0  7
1   3  1  c1  6
2   3  1  c2  7
3   3  1  c3  7
4   4  1  c0  7
5   4  1  c1  7
6   4  1  c2  7
7   4  1  c3  8
8   5  2  c0  5
9   5  2  c1  9
10  6  2  c0  5
11  6  2  c1  9
       d               
c     c0   c1   c2   c3
a b                    
3 1  7.0  6.0  7.0  7.0
4 1  7.0  7.0  7.0  8.0
5 2  5.0  9.0  NaN  NaN
6 2  5.0  9.0  NaN  NaN
---------drop duplicate to count the num of diff name -----------
    b   c  d
0  1  c0  7
1  1  c1  6
2  1  c2  7
3  1  c3  7
5  1  c1  7
7  1  c3  8
8  2  c0  5
9  2  c1  9
-------to find out which val diff twice in group------
       d
b c    
1 c0  1
  c1  2
  c2  1
  c3  2
2 c0  1
  c1  1
(1, 'c1') <class 'tuple'> <<<<<diff columns>>>>
(1, 'c3') <class 'tuple'> <<<<<diff columns>>>>
-------Before filter---------
       d               
c     c0   c1   c2   c3
a b                    
3 1  7.0  6.0  7.0  7.0
4 1  7.0  7.0  7.0  8.0
5 2  5.0  9.0  NaN  NaN
6 2  5.0  9.0  NaN  NaN
-------After filter---------
       d     
c     c1   c3
a b          
3 1  6.0  7.0
4 1  7.0  8.0
5 2  9.0  NaN
6 2  9.0  NaN

Process finished with exit code 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值