[深入浅出pandas]ch5高级操作

对DataFrame其中一列进行逻辑计算,会产生一个对应的由布尔值组成的Series

in:
df.Q1>36
out:
0      True
1     False
2      True
3      True
4      True
      ...

95     True
96    False
97     True
98    False
99    False
Name: Q1, Length: 100, dtype: bool

也可针对索引进行逻辑判断

in:
df.index ==1
out:
array([False,  True, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False])
in:
df.loc[:,'Q1':'Q4']>60

out:
    Q1  Q2  Q3  Q4
0   True    False   False   True
1   False   False   False   False
2   False   False   False   True
3   True    True    True    True
4   True    False   True    True
... ... ... ... ...

95  False   False   True    True
96  False   False   False   False
97  True    True    False   False
98  False   True    False   True
99  False   False   False   True
100 rows × 4 columns

除了支持逻辑运算,Pandas还支持组合条件的Python位运算

in:
#Q1成绩不小于60分,并且是C组成员
~(df.Q1 < 60) & (df['team'] == 'C')
out:
0     False
1     False
2     False
3      True
4     False
      ...

95    False
96    False
97     True
98    False
99    False
Length: 100, dtype: bool

示例:

df[df['Q1'] == 8]
df[~(df['Q1'] == 8)]
df[df.name == 'Ben']
df[df.Q1>df.Q2]
df.loc[df['Q1'] > 90,'Q1':]
df.loc[(df.Q1>80)&(df.Q2<15)] df.loc[(df.q1>90)|(df.Q2<90)] df.loc[df['q1']="=" 8]< code></90)]></15)]>

需要注意的是在进行 或(|)、 与(&) 、 非(~) 运算时,各个独立逻辑表达式需要用括号括起来

any 和 all对逻辑计算后的布尔序列再进行判断,序列中所有值都为True时all才返回True,序列中只要有一个值位True时any就返回True。还可以传入axis参数,来指定判断方向

#Q1,Q2&#x6210;&#x7EE9;&#x5168;&#x4E3A;&#x8D85;&#x8FC7;80&#x5206;&#x7684;
df[(df.loc[:,['Q1','Q2']] > 80).all(1)]

#Q1,Q2&#x6210;&#x7EE9;&#x81F3;&#x5C11;&#x6709;&#x4E00;&#x4E2A;&#x8D85;&#x8FC7;80&#x7684;
df[(df.loc[:,['Q1','Q2']]>80).any(1)

上述对两个列整体先做逻辑计算得到一个两列的布尔序列,然后用all和any在行方向上做逻辑运算

可以在表达式处使用lambda函数,默认变量是其操作的对象。如果操作的对象是一个DataFrame,那么变量就是这个DataFrame,如果是一个Series,那么就是这个Series

in:
s = df.Q1
#&#x67E5;&#x8BE2;&#x6700;&#x5927;&#x7D22;&#x5F15;&#x7684;&#x503C;
df.Q1[lambda s: max(s.index)]
out:
21

in:
#&#x8BA1;&#x7B97;&#x6700;&#x5927;&#x503C;
max(df.Q1.index)

对Pandas的一些比较函数,使我们可以将逻辑表达式替换为函数形式

#&#x4EE5;&#x4E0B;&#x76F8;&#x5F53;&#x4E8E;df[df.Q1 == 60]
df[df.Q1.eq(60)]

除了.eq(),还有:

df.ne()  #&#x4E0D;&#x7B49;&#x4E8E;!=
df.le()  #&#x5C0F;&#x4E8E;&#x7B49;&#x4E8E; <= df.lt() #小于< df.ge() #大于等于>=
df.gt()  #&#x5927;&#x4E8E;></=>

实例:

df[df.Q1.ne(89)]  #Q1&#x4E0D;&#x7B49;&#x4E8E;89
df.loc[df.Q1.gt(90) & df.Q2.lt(90)] #and&#x5173;&#x7CFB;&#xFF0C;Q1>90, Q2<90< code></90<>

这些函数可以传入一个定值、数列、布尔序列、Series或DataFrame,来与原数据比较

另外还有一个.isin()函数,用于判断数据是否包含指定内容。可以传入一个列表,原数据只要满足其中一个存在即可,也可以传入一个字典,键为列名,值为需要匹配的值,以实现按列个性化匹配存在值

df[df.team.isin(['A','B'])]
df[df.isin({'team':['C','D'],'Q1':[36,93]})]#&#x590D;&#x6742;&#x67E5;&#x8BE2;&#xFF0C;&#x5176;&#x4ED6;&#x503C;&#x4E3A;NaN

df.query(expr)使用布尔表达式查询DataFrame的列,表达式是一个字符串

df.query('Q1>Q2>90')
df.query('Q1+Q2>180')
df.query('(Q1<50)&(q2>40) and (Q3>90)')
df.query('team not in ("E","A","B")')
#&#x5BF9;&#x4E8E;&#x540D;&#x79F0;&#x4E2D;&#x5E26;&#x6709;&#x7A7A;&#x683C;&#x7684;&#x5217;&#xFF0C;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x53CD;&#x5F15;&#x53F7;&#x5F15;&#x8D77;&#x6765;
df.query('B == team name')</50)&(q2>

还支持用@符号引入变量

a = df.Q1.mean()
df.query('Q1>@a+40')
df.query('Q1>Q2+@a')

df.eval()和df.query()类似,也可以用于表达式筛选

df[df.eval("Q1>90>Q3>10")]
df[df.eval("Q1>Q2+@a")]

df.filter()可以对行名和列名进行筛选,支持模糊匹配、正则表达式

df.filter(items = ['Q1','Q2']) #&#x9009;&#x62E9;&#x4E24;&#x5217;
df.filter(regex = 'Q',axis = 1) #&#x5217;&#x540D;&#x5305;&#x542B;Q&#x7684;&#x5217;
df.filter(regex = 'e$',axis = 1) #&#x4EE5;e&#x7ED3;&#x5C3E;&#x7684;&#x5217;
df.filter(like = '2',axis = 0) #&#x7D22;&#x5F15;&#x4E2D;&#x6709;2&#x7684;
df.filter(regex = '^2',axis = 0).filter(like = 'Q',axis =1) #&#x7D22;&#x5F15;&#x4E2D;&#x4EE5;2&#x5F00;&#x5934;&#xFF0C;&#x5217;&#x540D;&#x6709;Q&#x7684;

df.select_dtypes(include = None,exclude = None)

可以指定包含和不包含的数据类型,如果只有一个类型,传入字符,如果有多个类型,传入列表

df.select_dtypes(include = ['float64'])
df.select_dtypes(exclude = ['int'])

若没有满足条件的数据,则返回一个仅有索引的DataFrame

加载数据时指定数据各列的类型:

#&#x5BF9;&#x6240;&#x6709;&#x5B57;&#x6BB5;&#x6307;&#x5B9A;&#x540C;&#x4E00;&#x7C7B;&#x578B;
df = pd.DataFrame(data,dtype = 'float32')
#&#x5BF9;&#x6BCF;&#x4E2A;&#x5B57;&#x6BB5;&#x5206;&#x522B;&#x6307;&#x5B9A;
df = pd.read_excel(data,dtype = {'team':'string','Q1':'int32'})

2.1推断类型

Pandas可以用以下方法智能地推断各列的数据类型,会返回一个按推断修改后的DataFrame。如果需要使用这些类型的数据,可以赋值替换

#&#x81EA;&#x52A8;&#x8F6C;&#x6362;&#x5408;&#x9002;&#x7684;&#x6570;&#x636E;&#x7C7B;&#x578B;
df.infer_objects()  #&#x63A8;&#x65AD;&#x540E;&#x7684;DataFrame
df.infer_objects().dtypes

out:
    name    team    Q1  Q2  Q3  Q4
0   Liver   E   89  21  24  64
1   Arry    C   36  37  37  57
2   Ack A   57  60  18  84
3   Eorge   C   93  96  71  78
4   Oah D   65  49  61  86
... ... ... ... ... ... ...

95  Gabriel C   48  59  87  74
96  Austin7 C   21  31  30  43
97  Lincoln4    C   98  93  1   20
98  Eli E   11  74  58  91
99  Ben E   21  43  41  74
100 rows &#xD7; 6 columns

name    object
team    object
Q1       int64
Q2       int64
Q3       int64
Q4       int64
dtype: object
#&#x63A8;&#x8350;&#x8FD9;&#x4E2A;&#x65B0;&#x65B9;&#x6CD5;&#xFF0C;&#x652F;&#x6301;string&#x7C7B;&#x578B;
df.convert_dtypes()  #&#x63A8;&#x65AD;&#x540E;&#x7684;DataFrame
df.convert_dtypes().dtypes

out:

name    team    Q1  Q2  Q3  Q4
0   Liver   E   89  21  24  64
1   Arry    C   36  37  37  57
2   Ack A   57  60  18  84
3   Eorge   C   93  96  71  78
4   Oah D   65  49  61  86
... ... ... ... ... ... ...

95  Gabriel C   48  59  87  74
96  Austin7 C   21  31  30  43
97  Lincoln4    C   98  93  1   20
98  Eli E   11  74  58  91
99  Ben E   21  43  41  74
100 rows &#xD7; 6 columns

name    string
team    string
Q1       Int64
Q2       Int64
Q3       Int64
Q4       Int64
dtype: object

pd.to_xxx 系统方法可以将数据安全转换,errors参数可以实现无法转换则转换为兜底类型:

#&#x6309;&#x5927;&#x4F53;&#x7C7B;&#x578B;&#x63A8;&#x65AD;
m = ['1',2,3]
s = pd.to_numeric(s)#&#x8F6C;&#x6210;&#x6570;&#x5B57;
pd.to_datetime(m) #&#x8F6C;&#x6210;&#x65F6;&#x95F4;
pd.to_timedelta #&#x8F6C;&#x6210;&#x65F6;&#x95F4;&#x5DEE;
pd.to_datetime(m,errors = 'coerce') #&#x9519;&#x8BEF;&#x5904;&#x7406;
pd.to_numeric(m,errors = 'coerce').fillna(0) #&#x515C;&#x5E95;&#x586B;&#x5145;
pd.to_datetime(df[['year','month','day']])  #&#x7EC4;&#x5408;&#x6210;&#x65E5;&#x671F;

转换成数字类型时,默认返回的dtype使float64还是int64取决于提供的数据,使用downcast参数获得向下转换后的其他类型

#&#x6700;&#x4F4E;&#x671F;&#x671B;
pd.to_numeric(m,downcast = 'integer')  #&#x81F3;&#x5C11;&#x4E3A;&#x6709;&#x7B26;&#x53F7;int&#x6570;&#x636E;&#x7C7B;&#x578B;
pd.to_numeric(m,downcast = 'float')   #&#x81F3;&#x5C11;&#x4E3A;float&#x6D6E;&#x70B9;&#x7C7B;&#x578B;
df.Q1.astype('int32')

pd.to_datetime()和s.astype(‘datetime64[ns]’)来做时间类型转换

df.sort_index()实现按索引排序,默认以从小到大的升序方式排列。如果希望按降序排序,传入ascending = False。可以传入axis = 1来列索引方向上排序。

若想改变原数据,传入inplace = True

参数:na_position = ‘first’ 表示空值在前,如果是last表示空值在后

传入level = 1,表示如果有多层,排一级

df.reindex()指定自己定义顺序的索引,实现行和列的顺序重新定义:

df = pd.DataFrame({
    'A':[1,2,3],
    'B':[4,5,6]
},index = ['a','b','c'])
#&#x6309;&#x8981;&#x6C42;&#x91CD;&#x65B0;&#x6307;&#x5B9A;&#x7D22;&#x5F15;&#x987A;&#x5E8F;
df.reindex(['c','b','a'])
#&#x6307;&#x5B9A;&#x5217;&#x987A;&#x5E8F;
df.reindex(['B','A'],axis = 1)

数值排序主要使用sort_values()

数字按大小顺序,字符按字母顺序

Series和DataFrame都支持此方法

df.Q1.sort_values()
df.sort_values('Q4')

默认升序,但可以指定排序方式

df.sort_values(by = ['team','name'],ascending = [True,False])

其他参数:

ascending = True/False

inplace = True/False

na_position = ‘first’/’last’

df.sort_values(by = [‘xx’]) 按指定字段排列

df.sort_values(‘Q1’)

df.sort_values(‘team’,ignore_index = True) #索引重新0-(n-1)排

有时需要使用索引和数据值混合排序,需要先给索引起名,再进行排序

df.set_index('name',inplace = True) #&#x8BBE;&#x7F6E;name&#x4E3A;&#x7D22;&#x5F15;
df.index.names = ['s_name'] #&#x7ED9;&#x7D22;&#x5F15;&#x8D77;&#x540D;
df.sort_values(by = ['s_name','team'])  #&#x6392;&#x5E8F;

nsmallest() 和nlargest()用来实现数字列的排序,并可以指定返回的个数

df.nsmallest(5,['Q1','Q2']) #&#x5148;&#x6309;Q1&#x6700;&#x5C0F;&#x5728;&#x524D;&#xFF0C;&#x5982;&#x679C;&#x76F8;&#x540C;&#xFF0C;Q2&#x5C0F;&#x7684;&#x5728;&#x524D;

以上显示前五个最小的数,仅支持数字类型的排序

s&#x662F;&#x4E00;&#x7EC4;series&#x6570;&#x636E;
s.nsmallest(3)  #&#x6700;&#x5C0F;&#x7684;3&#x4E2A;

修改数据

先筛选出需要修改的数值范围,再为这个范围重新赋值

#&#x5C06;&#x5C0F;&#x4E8E;60&#x5206;&#x7684;&#x6210;&#x7EE9;&#x4FEE;&#x6539;&#x4E3A;60
df[df.Q1<60] = 60< code></60]>

替换数据

replace方法

df.replace(0,5) #&#x5C06;&#x6570;&#x636E;&#x4E2D;&#x6240;&#x6709;&#x7684;0&#x6362;&#x4E3A;5
df.replace([0,1,2,3],4) #&#x5C06;0-3&#x6362;&#x4E3A;4
df.replace([0,1,2,3],[4,3,2,1]) #&#x5BF9;&#x5E94;&#x4FEE;&#x6539;
s.replace([1,2],method = 'bfill') #&#x5411;&#x4E0B;&#x586B;&#x5145;
df.replace({0:10,1:100})
df.replace({'Q1':0,'Q2':5},100) #&#x5C06;&#x6307;&#x5B9A;&#x5B57;&#x6BB5;&#x7684;&#x6307;&#x5B9A;&#x503C;&#x4FEE;&#x6539;&#x4E3A;100

在传递值时,也可以使用正则表达式

填充缺失值

df.fillna(0) #&#x5C06;&#x7A7A;&#x503C;&#x5168;&#x4FEE;&#x6539;&#x4E3A;0
df.fillna(method = 'ffill') #&#x5C06;&#x7A7A;&#x503C;&#x90FD;&#x4FEE;&#x6539;&#x4E3A;&#x524D;&#x4E00;&#x4E2A;&#x503C;
values = {'A':0,'B':1,'C':2}
df.fillna(value = values) #&#x4E3A;&#x5404;&#x5217;&#x586B;&#x5145;&#x4E0D;&#x540C;&#x7684;&#x503C;
df.fillna(value = values,limit) #&#x53EA;&#x66FF;&#x6362;&#x7B2C;&#x4E00;&#x4E2A;

修改索引名

最常用的方法是df.index和df.columns重新赋值为一个类似于列表的序列值,这会将其覆盖为指定序列中的名称。

使用df.rename和df.rename_axis对轴名称进行修改

df.rename(columns = {'team':'class'}) #&#x5C06;team&#x4FEE;&#x6539;&#x4E3A;class

插入列

df.insert()

insert()方法可以传入三个主要参数:loc是一个数字,表示新列所在的位置,使用列的数组索引,第二个参数column为新的列名,最后一个参数value为列的值,一般是一个series

df.insert(2,'total',df.sum(1))  #&#x503C;&#x4E3A;&#x6BCF;&#x884C;&#x7684;&#x603B;&#x6210;&#x7EE9;

如果已经存在相同的数据列,会报错,可以传入allow_duplicates = True插入一个同名的列

指定列df.assign()

df.assign(k=v)为指定一个新列的操作,k为新列的列名,v为此列的值,v必须是一个与原数据同索引的Series。

这个方法在链式编程技术中比较重要。

我们平时在做数据探索分析时会增加一些临时列,如果新列全部使用赋值的方式生成,则会造成原数据混乱,因此需要一个方法来让我们不用赋值也可以创建一个临时的列。这种思路也适用于所有对原数据的操作,建议在未最终确定数据处理方案时,除了必要的数据整理工作,均使用链式方法。

#&#x589E;&#x52A0;total&#x5217;
df.assign(total = df.sum(1))
#&#x539F;&#x6570;&#x636E;&#x6CA1;&#x6709;&#x53D8;&#x5316;
#&#x589E;&#x52A0;&#x4E24;&#x5217;
df.assign(total = df.sum(1),Q = 100) #Q&#x8FD9;&#x4E00;&#x5217;&#x7684;&#x503C;&#x5747;&#x4E3A;100
df.assign(total = df.sum(1)).assign(Q=100) #&#x6548;&#x679C;&#x540C;&#x4E0A;
#&#x518D;&#x589E;&#x52A0;&#x4E24;&#x5217;name_len&#x548C;avg
#&#x4F7F;&#x7528;&#x94FE;&#x5F0F;&#x65B9;&#x6CD5;&#xFF1A;
(
    df.assign(total = df.sum(1))#&#x603B;&#x6210;&#x7EE9;
    .assign(Q = 100) #&#x76EE;&#x6807;&#x6EE1;&#x5206;&#x503C;
    .assign(name_len = df.name.str.len())
    .assign(avg = df.mean(1)) #&#x5E73;&#x5747;&#x503C;
    .assign(avg2 = lambda d:d.total/4)  #&#x5E73;&#x5747;&#x503C;2
)

要特别说明的是avg2列,因为df实际是没有total这一列的,如果我们需要使用total列,就需要使用lambda来调用。lambda中的第一个参数d是代码执行到本行前的DataFrame内容,可以认为是一个虚拟的DataFrame实体,然后用变量d使用这个DataFrame的数据。这个d是变量名,可以任意命名

执行表达式df.eval()

df.eval()与之前介绍的df.query()一样,可以以字符的形式传入表达式,增加列数据。下面以增加总分为例

df.eval('total = Q1+Q2+Q3+Q4')
df['C1'] = df.eval('Q2+Q3')
a = df.Q1.mean()
df.eval("C3 = Q3+@a")
df.eval("C3 = Q2>(Q3+@a)")

df.append()可以追加一个新行

#&#x8FFD;&#x52A0;&#x5408;&#x5E76;
df = pd.DataFrame([[1,2],[3,4,]],columns = list('AB'))
df2 = pd.DataFrame([[5,6],[7,8]],columns = list('AB'))
df.append(df2)

追加合并

df.append()可以追加一个新行

pd.concat([s1,s2])可以将两个df或s连接起来:

s1 = pd.Series(['a','b'])
s2 = pd.Series(['c','d'])
pd.concat([s1,s2])
pd.concat([s1,s2],ignore_index = True)

删除有两种方法:一种是pop()函数,使用pop(),Series会删除指定索引的数据并同时返回这个被删除的值,DataFrame会删除指定列并返回这个被删除的列。

还有一种是反选法,将需要的数据筛选出来赋值给原变量,最终实现删除

df.where()中可以传入一个布尔表达式、布尔值的Series/DataFrame、序列或者可以调用的对象,然后与原数据做对比,返回一个行索引与列索引与原数据相同的数据,且在满足条件的位置保留原值,在不满足条件的位置填充NaN

df = df.select_dtypes(include = 'number')
df.where(df>70)

传入一个可调用对象,比如lambda

df.where(lambda d:d.Q1>50)

可以指定将不满足条件的值替换为指定值

#&#x5927;&#x4E8E;&#x7B49;&#x4E8E;60&#x5206;&#x7684;&#x663E;&#x793A;&#x6210;&#x7EE9;&#xFF0C;&#x5C0F;&#x4E8E;&#x7684;&#x663E;&#x793A;&#x201C;&#x4E0D;&#x53CA;&#x683C;&#x201D;
df.where(df>=60,'&#x4E0D;&#x53CA;&#x683C;')

可以传入一个算法

#c&#xFF1A;&#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#x6570;&#x662F;&#x5426;&#x4E3A;&#x5076;&#x6570;&#x7684;&#x8868;&#x8FBE;&#x5F0F;
c = df%2 == 0
#&#x4F20;&#x5165;c&#xFF0C;&#x4E3A;&#x5076;&#x6570;&#x65F6;&#x663E;&#x793A;&#x539F;&#x503C;&#x51CF;&#x53BB;20&#x540E;&#x7684;&#x76F8;&#x53CD;&#x6570;
df.where(~c,-(df-20))

df.where()方法可以将满足条件的值筛选出来,将不满足的值替换为另一个值,但无法对满足条件的值进行替换。np.where()可以

#&#x5C0F;&#x4E8E;60&#x5206;&#x4E3A;&#x4E0D;&#x53CA;&#x683C;
np.where(df>=60,'&#x5408;&#x683C;','&#x4E0D;&#x53CA;&#x683C;')  #&#x8FD4;&#x56DE;&#x7684;&#x662F;&#x4E00;&#x4E2A;&#x4E8C;&#x7EF4;array
#&#x8BA9;df.where()&#x4E2D;&#x7684;&#x6761;&#x4EF6;&#x4E3A;&#x5047;&#xFF0C;&#x4ECE;&#x800C;&#x5E94;&#x7528;np.where()&#x7684;&#x8BA1;&#x7B97;&#x7ED3;&#x679C;
df.where(df == 65164815165,np.where(df>=60,'&#x5408;&#x683C;','&#x4E0D;&#x5408;&#x683C;'))
(
    df.assign(avg = df.mean(1)) #&#x8BA1;&#x7B97;&#x4E00;&#x4E2A;&#x5E73;&#x5747;&#x6570;
    .assign(&#x53CA;&#x683C; = lambda d:np.where(d.avg>=60,'&#x662F;','&#x5426;')) #&#x901A;&#x8FC7;np.where()&#x5224;&#x65AD;&#x5E73;&#x5747;&#x5206;&#x662F;&#x5426;&#x53CA;&#x683C;
)

df.mask()的用法跟df.where()基本相同,唯一的区别是df.mask()将满足条件的位置填充为NaN,也可以指定填充值

语法:df.lookup(行标签,列标签),返回一个numpy.ndarrray,标签必须是一个序列

in:
#&#x884C;&#x5217;&#x76F8;&#x540C;&#x6570;&#x91CF;&#xFF0C;&#x8FD4;&#x56DE;&#x4E00;&#x4E2A;array
df.lookup([1,3,4],['Q1','Q2','Q3'])
out:
array([36, 96, 61], dtype=int64)

大多数据迭代用for

迭代索引和指定的多列,使用python内置的zip函数将其打包成可迭代的zip对象

#&#x8FED;&#x4EE3;&#x7D22;&#x5F15;&#x548C;&#x6307;&#x5B9A;&#x7684;&#x4E24;&#x5217;
for i,n,q in zip(df.index,df.name,df.Q1):
    print(i,n,q)

df.iterrows()生成一个可迭代对象,将DataFrame行作为(索引,行数据)组成的Series数据进行迭代。在for语句中需要两个变量来承接数据:一个作为索引变量,即使索引在迭代中不会使用(这种情况可以使用useless来作为变量名);另一个为数据变量,读取具体列时,可以使用字典的方法和对象属性的方法。

此段代码作用同上

#&#x8FED;&#x4EE3;&#xFF0C;&#x4F7F;&#x7528;name,Q1&#x6570;&#x636E;
for index,row in df.iterrows():
    print(index,row['name'],row.Q1)

df.iterrows()是最常用、最方便的按行迭代方法

df.itertuples()生成一个nametuples类型数据,name默认名为Pandas,可以在参数中指定

in:
for row in df.itertuples():
    print(row)

out:
Pandas(Index=0, name='Liver', team='E', Q1=89, Q2=21, Q3=24, Q4=64)
Pandas(Index=1, name='Arry', team='C', Q1=36, Q2=37, Q3=37, Q4=57)
Pandas(Index=2, name='Ack', team='A', Q1=57, Q2=60, Q3=18, Q4=84)
Pandas(Index=3, name='Eorge', team='C', Q1=93, Q2=96, Q3=71, Q4=78)
Pandas(Index=4, name='Oah', team='D', Q1=65, Q2=49, Q3=61, Q4=86)
Pandas(Index=5, name='Harlie', team='C', Q1=24, Q2=13, Q3=87, Q4=43)
......

for row in df.itertuples(index = False,name = 'Gairuo'):
    print(row)
    print(row.Index,row.name)

df.items()和dfiteritems()功能相同,它迭代时返回一个(列名,本列的Series结构数据),实现对列的迭代

in:
#Series&#x53D6;&#x524D;&#x4E09;&#x4E2A;
for label,ser in df.items():
    print(label)
    print(ser[:3],end = '\n\n')

out:
name
0    Liver
1     Arry
2      Ack
Name: name, dtype: object

team
0    E
1    C
2    A
Name: team, dtype: object

Q1
0    89
1    36
2    57
Name: Q1, dtype: int64

Q2
0    21
1    37
2    60
Name: Q2, dtype: int64

Q3
0    24
1    37
2    18
Name: Q3, dtype: int64

Q4
0    64
1    57
2    84
Name: Q4, dtype: int64

如果需要对Series的数据再进行迭代,可嵌套for循环

除了df.items(),如果需要迭代一个DataFrame的列,可以直接对DataFrame迭代,会循环得到列名

#&#x76F4;&#x63A5;&#x5BF9;DataFrame&#x8FED;&#x4EE3;&#xFF1A;
for column in df:
    print(column)
#&#x4F9D;&#x6B21;&#x53D6;&#x51FA;&#x6BCF;&#x4E2A;&#x5217;
for column in df:
    print(df[column])
#&#x53EF;&#x5BF9;&#x6BCF;&#x4E2A;&#x5217;&#x7684;&#x5185;&#x5BB9;&#x8FDB;&#x884C;&#x8FED;&#x4EE3;
for column in df:
    for i in df[column]:
        print(i)

#&#x8FED;&#x4EE3;&#x6307;&#x5B9A;&#x5217;
for i in df.name:
    print(i)

#&#x53EA;&#x8FED;&#x4EE3;&#x60F3;&#x8981;&#x7684;&#x5217;
l = ['name','Q1']
cols = df.columns.intersection(l)
for col in cols:
    print(col)

pipe()叫做管道方法。可以让我们写的分析过程标准化、流水线化,达到复用目标。

DataFrame和Series都支持pipe()方法。语法结构为:

df.pipe(函数名,传给函数的参数列表或字典)

它将DataFrame或Series作为函数的第一个参数,可以根据需求返回自己定义的任意类型数据

pipe可以将复杂的调用简化

#&#x5BF9;df&#x591A;&#x91CD;&#x5E94;&#x7528;&#x591A;&#x4E2A;&#x51FD;&#x6570;
f(g(h(df),arg1 = a),arg2 = b,arg3 = c)
#arg&#x662F;&#x4F20;&#x5165;&#x7684;&#x53C2;&#x6570;
#&#x7528;pipe()&#x53EF;&#x4EE5;&#x5C06;&#x5B83;&#x4EEC;&#x8FDE;&#x63A5;&#x8D77;&#x6765;
(
    df.pipe(h)
    .pipe(g,arg1 = a)
    .pipe(f,arg2 = b,arg3 = c)
)
#&#x4EE5;&#x4E0B;&#x662F;&#x5C06;arg2&#x53C2;&#x6570;&#x4F20;&#x7ED9;&#x51FD;&#x6570;f&#xFF0C;&#x7136;&#x540E;&#x4F5C;&#x4E3A;&#x51FD;&#x6570;&#x6574;&#x4F53;&#x63A5;&#x53D7;&#x540E;&#x9762;&#x7684;&#x53C2;&#x6570;
(
    df.pipe(h)
    .pipe(g,arg1 = a)
    .pipe((f,'arg2'),arg1 = a,arg3 = c)
)

实例:

#&#x5B9A;&#x4E49;&#x4E00;&#x4E2A;&#x51FD;&#x6570;&#xFF0C;&#x7ED9;&#x6240;&#x6709;&#x5B63;&#x5EA6;&#x7684;&#x6210;&#x7EE9;&#x52A0;n&#xFF0C;&#x7136;&#x540E;&#x589E;&#x52A0;&#x5E73;&#x5747;&#x6570;
#&#x5176;&#x4E2D;n&#x4E2D;&#x8981;&#x52A0;&#x7684;&#x503C;&#x4E3A;&#x5FC5;&#x4F20;&#x53C2;&#x6570;
def add_mean(rdf,n):
    df = rdf.copy()
    df = df.loc[:,'Q1':'Q4'].applymap(lambda x:x+n)
    df['avg'] = df.loc[:,'Q1':'Q4'].mean(1)
    return df

#&#x8C03;&#x7528;
df.pipe(add_mean,100) #&#x5C06;100&#x4F5C;&#x4E3A;&#x53C2;&#x6570;&#x4F20;&#x5165;&#x51FD;&#x6570;add_mean

下例完成了一个数据筛选需求,lambda的第一个参数为self,即使用前的数据本身,后面的参数可以在逻辑代码中使用

#&#x7B5B;&#x9009;&#x51FA;Q1&#x5927;&#x4E8E;&#x7B49;&#x4E8E;80&#x4E14;Q2&#x5927;&#x4E8E;&#x7B49;&#x4E8E;90&#x7684;&#x6570;&#x636E;
df.pipe(lambda df_,x,y:
       df_[(df_.Q1 >= x) & (df.Q2 >= y)],80,90)

apply()可以对DataFrame按行和列(默认)进行函数处理,也支持Series。如果是Series,逐个传入具体值,DataFrame逐行或逐列传入

#&#x5C06;&#x6587;&#x672C;&#x5168;&#x90E8;&#x8F6C;&#x6362;&#x4E3A;&#x5168;&#x5C0F;&#x5199;
#&#x5C06;name&#x5168;&#x90E8;&#x53D8;&#x4E3A;&#x5C0F;&#x5199;
df.name.apply(lambda x: x.lower())
#&#x53BB;&#x6389;&#x4E00;&#x4E2A;&#x6700;&#x9AD8;&#x5206;&#x548C;&#x6700;&#x4F4E;&#x5206;&#x518D;&#x7B97;&#x51FA;&#x5E73;&#x5747;&#x5206;
def my_mean(s):
    max_min_ser = pd.Series([-s.max(),-s.min()])
    return s.append(max_min_ser).sum()/(s.count()-2)
#&#x5BF9;&#x6570;&#x5B57;&#x5217;&#x5E94;&#x7528;&#x51FD;&#x6570;
df.select_dtypes(include = 'number').apply(my_mean)

这段代码里,函数my_mean接收一个Series,从此Series中取最大值和最小值的负值组成一个需要减去的负值Series,传入的Series追加词负值,最后求和,并取平均值

df.applymap()可以实现元素级函数应用,即对DataFrame中所有的元素(不包括索引)应用函数处理

#&#x8BA1;&#x7B97;&#x6570;&#x636E;&#x7684;&#x957F;&#x5EA6;
def mylen(x):
    return len(str(x))

df.applymap(lambda x:mylen(x))  #&#x5E94;&#x7528;&#x51FD;&#x6570;
df.applymap(mylen)  #&#x6548;&#x679C;&#x540C;&#x4E0A;

map()根据输入对应关系映射值返回最终数据,用于Series对象或DataFrame对象的一列。传入的值可以是一个字典,键为原数据值,值为替换后的值。

可以传入一个函数(参数为Series的每个值),还可以传入一个字符格式化表达式来格式化数据内容

df.team.map({'A':'&#x4E00;&#x73ED;','B':'&#x4E8C;&#x73ED;','C':'&#x4E09;&#x73ED;','D':'&#x56DB;&#x73ED;'}) #&#x679A;&#x4E3E;&#x66FF;&#x6362;
#&#x6BCF;&#x5217;&#x7684;&#x6700;&#x5927;&#x503C;
df.agg('max')
#&#x5C06;&#x6240;&#x6709;&#x5217;&#x805A;&#x5408;&#x4EA7;&#x751F;sum&#x548C;min&#x4E24;&#x884C;
df.agg(['sum','min'])
#&#x5E8F;&#x5217;&#x591A;&#x4E2A;&#x805A;&#x5408;
df.agg({'Q1':['sum','min'],'Q2':['min','max']})
#&#x5206;&#x7EC4;&#x540E;&#x805A;&#x5408;
df.groupby('team').agg('max')
df.Q1.agg(['sum','mean'])

agg()还支持传入函数的位置参数和关键字参数,支持每个列分别用不同的方法聚合,支持指定轴的方向

DataFrame和Series自身调用函数并返回一个与自身长度相同的数据

如:df.transform(lambda x:x*2)

Original: https://blog.csdn.net/m0_73598509/article/details/127413593
Author: 起风了xxx
Title: [深入浅出pandas]ch5高级操作

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/738983/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球