一、删除相关
1.DataFrame.dropna()
DataFrame.dropna(self,axis=0,how=‘any’,thresh=None,subset=None,inplace=False):删除空值
axis | {0或index,1或columns},默认0,删除包含缺失值的行或列。0或index:删除包含缺失值的行;1或columns:删除包含缺失值的列 |
how | {any 或 all } ,默认为any。‘any’:如果存在任何nan值,则删除该行或列;‘all’:如果所有值均为nan,则删除该行或列 |
thresh | int,可选,需要许多非nan值 |
subset | 类数组,可选。要考虑的其他轴上的标签。例如,如果要删除行,这些标签将是要包括的列的列表。 |
inplace | bool 默认为False.如果为True,则执行基地操作并返回None |
返回 | 删除了NA条目的DataFrame |
补充:pd.NaT:缺失时间 |
import pandas as pd
import numpy as np
df = pd.DataFrame({
"name":["Alfle","Bat","Cow"],
"toy":[np.nan,"Batmobile","Bullwhip"],
"born":[pd.NaT,pd.Timestamp("1940-04-25"),pd.NaT]
})
print("原始数据")
print(df)
print("-"*15)
print("删除至少缺少一个元素的行")
print(df.dropna())
print("-"*15)
print("删除至少缺少一个元素的列")
print(df.dropna(axis='columns'))
print("-"*15)
print("删除缺少所有元素的行")
print(df.dropna(how="all"))
print("-"*15)
print("只保留至少有两个非NA值的行")
print(df.dropna(thresh=2))
print("-"*15)
print("定义在哪些列中查找缺失值")
print(df.dropna(subset=['name','toy']))
print("-"*15)
print("将有有效条目的DataFrame保留在同一变量中")
df_two = df.dropna(inplace=True) #结果有点问题
print(df_two)
#结果:
原始数据
name toy born
0 Alfle NaN NaT
1 Bat Batmobile 1940-04-25
2 Cow Bullwhip NaT
---------------
删除至少缺少一个元素的行
name toy born
1 Bat Batmobile 1940-04-25
---------------
删除至少缺少一个元素的列
name
0 Alfle
1 Bat
2 Cow
---------------
删除缺少所有元素的行
name toy born
0 Alfle NaN NaT
1 Bat Batmobile 1940-04-25
2 Cow Bullwhip NaT
---------------
只保留至少有两个非NA值的行
name toy born
1 Bat Batmobile 1940-04-25
2 Cow Bullwhip NaT
---------------
定义在哪些列中查找缺失值
name toy born
1 Bat Batmobile 1940-04-25
2 Cow Bullwhip NaT
---------------
将有有效条目的DataFrame保留在同一变量中
None
2.DataFrame.drop_duplicates()
drop_duplicates():返回删除了重复行的DataFrame,可选择仅考虑某些列。包括时间索引在内的索引将被忽略。
subset | 列标签或标签序列,可选。仅考虑用于签重复项的某列,默认情况下使用所有列 |
keep | {‘first’,‘last’,False},-first:删除除第一次出现的重复项,-last:删除除最后一次出现的重复项。-False:删除所有重复项 |
inplacc | 布尔值,默认为False,是否删除重复项或返回副本 |
返回 | 删除了重复行的DataFrame |
import pandas as pd
test_dict = {
"name":["Tom","Tom","Tom","Marry","John","John"],
"fruit":["apple","apple","peach","peach","banana","banana"],
"price":[3,3,5,6,7,8]
}
df = pd.DataFrame(test_dict)
print(df)
print("-"*15)
#默认情况下,它会根据所有列删除重复的行
new_df = df.drop_duplicates()
print(new_df)
print("-"*15)
#要删除特定列上的重复项,使用subset
df_subset = df.drop_duplicates(subset=["name"])
print(df_subset)
print("-"*15)
#要删除重复项并保留最后一次,使用keep
df_keep_two = df.drop_duplicates(subset=["name","fruit"],keep='last')
print(df_keep_two)
print("-"*15)
df_keep_three = df.drop_duplicates(subset=["name","fruit"],keep='first')
print(df_keep_three)
#结果:
name fruit price
0 Tom apple 3
1 Tom apple 3
2 Tom peach 5
3 Marry peach 6
4 John banana 7
5 John banana 8
---------------
name fruit price
0 Tom apple 3
2 Tom peach 5
3 Marry peach 6
4 John banana 7
5 John banana 8
---------------
name fruit price
0 Tom apple 3
3 Marry peach 6
4 John banana 7
---------------
name fruit price
1 Tom apple 3
2 Tom peach 5
3 Marry peach 6
5 John banana 8
---------------
name fruit price
0 Tom apple 3
2 Tom peach 5
3 Marry peach 6
4 John banana 7
3.DataFrame.drop()
DataFrame.drop(labels=None,axis=0,index=None,columns=None,level=None,inplace=False,errors=‘raise’):从行或列中删除指定的标签。通过指定标签名和相应的轴,或直接指定索引或列名来删除行或列。使用索引时,可以通过指定级别来移除不同级别的标签
labels | :单标签或者类似列表。要删除的索引或列标签。元组将用作单个标签,而不被视为类似列表 |
axis | {0或‘index’,1或‘columns’} ,默认0。按照索引或列中删除标签 |
index | 单个索引或类似列表。替代指定轴(labels,axis=0 相当于index=labels) |
columns | 单个索引或类似列表。替代指定轴(labels,axis=1,相当于columns=labels) |
level | 整数或者层次名,可选。对于混合索引,是将要被移除的标签的层次 |
inplace | 布尔值,缺省为False。如果为False,返回一个副本,否则,就地执行操作并返回None |
errors | {‘ignore’,‘raise’} 默认‘raise’。如果‘ignore’,则抑制错误并且仅删除现有标签 |
返回值 | 没有删除索引列或列标签的DataFrame或None if inplace=True |
df = pd.DataFrame(np.arange(12).reshape(3,4),columns=['A','B','C','D'])
结果:
A B C D
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
# 删除列
df_one = df.drop(['B','C'],axis=1)
结果:
A D
0 0 3
1 4 7
2 8 11
df_two = df.drop(columns=['B','C'])
结果:
A D
0 0 3
1 4 7
2 8 11
# 按索引删除一行,左右都是闭区间
df_three = df.drop([0,1])
结果:
A B C D
2 8 9 10 11
# 删除MultiIndex DataFrame的列/行
midx = pd.MultiIndex(levels=[['sheep','cow','cat'],['speed','weight','length']],codes=[[0,0,0,1,1,1,2,2,2],[0,1,2,0,1,2,0,1,2]])
df = pd.DataFrame(index=midx,columns=['big','small'],data=[[45,30],[200,100],[1.5,1],[30,20],[250,150],[1.5,0.8],[320,250],[1,0.8],[0.3,0.2]])
原始dataframe:
big small
sheep speed 45.0 30.0
weight 200.0 100.0
length 1.5 1.0
cow speed 30.0 20.0
weight 250.0 150.0
length 1.5 0.8
cat speed 320.0 250.0
weight 1.0 0.8
length 0.3 0.2
# 从 MultiIndex DataFrame中删除特定的索引组合,即删除'cat'和'weight',它只删除对应的行
df.drop(index=('cat','weight')):
big small
sheep speed 45.0 30.0
weight 200.0 100.0
length 1.5 1.0
cow speed 30.0 20.0
weight 250.0 150.0
length 1.5 0.8
cat speed 320.0 250.0
length 0.3 0.2
df.drop(index='cow',columns='small'):
big
sheep speed 45.0
weight 200.0
length 1.5
cat speed 320.0
weight 1.0
length 0.3
df.drop(index='length',level=1) # level说明 length是哪一层索引
结果:
big small
sheep speed 45.0 30.0
weight 200.0 100.0
cow speed 30.0 20.0
weight 250.0 150.0
cat speed 320.0 250.0
weight 1.0 0.8
二、索引相关
1.DataFrame.sort_index()
DataFrame.sort_index(axis=0,level=None,ascending=True,inplace=False,kind=‘quicksort’,na_position=‘last’,sort_remaining=True,ignore_index=False,key=None)
按标签(沿轴)对对象排序
如果inplace参数为False,返回按标签排序的新DataFrame,否则更新原始DataFrame并返回None
axis | {0 或‘index’,1或‘columns’},默认为0,0表示行,1表示列 |
level | int 或level name 或 ints的list 或level names的list,如果不为None,则按指定索引级别的值排序 |
ascending | bool 或bools的list ,默认为True。升序和降序排序。当索引是多索引时,排序方向可以为每个级别单独控制 |
inplace | bool,默认为False。如果为True,就地执行操作 |
kind | {‘quicksort’,‘mergesort’,‘heapsort’}默认为’quicksort’。mergesort是唯一稳定的算法,对于DataFrame,仅在对单个列或标签进行排序时才应用此选项 |
na_position | {‘first’,‘last’ } 默认为‘last’,如果首先将NaN放在开头;最后将NaN放在最后。未针对MultiIndex实施。 |
sort_remaining | bool,默认为True.如果为True且按级别和索引排序是多层的,则在按指定级别排序后也按其他级别(按顺序)排序 |
ignore_index | bool,默认为False。如果为True,则结果轴将标记为0,1,…,n-1 |
key | callable,可选的。如果不是None,则在排序之前将函数应用于索引值。这类似于内建函数中的key参数sorted(),但值得注意的区别是此key函数应被向量化。它应期望index并返回具有相同形状的index。对于MultiIndex输入,将按级别应用key |
返回 | 原始DataFrame按标签排序 |
import pandas as pd
#默认情况下,它以升序排序,要想降序排序,使用ascending=False
test_dict = {
"A": [1,2,3,4,5]
}
df = pd.DataFrame(test_dict,index=[100,29,234,1,150])
print(df)
new_df = df.sort_index()
print(new_df)
new_descent_df = df.sort_index(ascending=False)
print(new_descent_df)
#结果:
A
100 1
29 2
234 3
1 4
150 5
A
1 4
29 2
100 1
150 5
234 3
A
234 3
150 5
100 1
29 2
1 4
# 可以指定在排序之前对索引的键进行处理
test_dict_two = {
"a":[1,2,3,4]
}
df_two = pd.DataFrame(test_dict_two,index=["A","b","C","d"])
print(df_two)
new_df_two = df_two.sort_index()
print(new_df_two)
new_key_df = df_two.sort_index(key=lambda x:x.str.lower())
print(new_key_df)
#结果:
a
A 1
b 2
C 3
d 4
a
A 1
C 3
b 2
d 4
a
A 1
b 2
C 3
d 4
2.DataFrame.reset_index()
3.DataFrame.isna()
检测缺失值。返回一个布尔值相同大小的对象,指示值是否为NA。例如None或numpy.NAN,被映射到True值。其他所有内容都被映射到False值。如空字符串‘’或numpy.inf不被视为NA值的字符(除非设置)
返回 | DataFrame,DataFrame中每个元素的布尔值掩码,指示每个元素是否为NA值 |
4.DataFrame.groupby()
groupby(by=None,axis =0,level=None,as_index=True,sort=True,group_keys=True,observed = False,dropna = True):使用映射器或一系列列对DataFrame进行分组
by | :映射、函数、标签或标签列表,用于确定groupby的组。如果by是一个函数,它会在对象索引的每个值上调用。如果传递了dict或Series,则Series或dict 的值将用于确定组。如果传递长度等于所选轴的列表qu或ndarray,则按原样使用这些值来确定组。标签或标签列可以按self.请注意,元组被解释为(单个)键 |
axis | {0 或‘index’,1 或‘columns’},默认为0,沿行(0)或列(1) 拆分 |
level | int,level name ,or sequence of such,default None,如果轴是MultiIndex(分层),则按特定级别或多个级别分组 |
as_index | 布尔值,默认为True,对于聚合输出,返回以组标签为索引的对象。仅与DataFrame输入相关。as_index=False 实际上是“SQL风格”的分组输出 |
sort | 布尔值,默认为True,对组键进行排序。关闭此功能会获得更好的性能。注意,这不会影响每组内的观察顺序。Groupby保留每个组内的行顺序 |
group_keys | 布尔值,默认为True,调用apply时,将组键添加到索引以识别片段 |
observed | 布尔值,默认为False,这仅适用于任何groupers是分类的。如果为真:仅显示分类分组的观察值。如果为False,显示分类分组的所有值 |
dropna | 布尔值,默认为True。如果为True,并且组键包含NA值,则NA值连同行/列都被删除。如果为False,NA值也将被视为组中的键 |
import pandas as pd
df = pd.DataFrame({
"animal":["falcon","falcon","parrot","parrot"],
"max speed":[380,370,24,26]
})
print(df)
print(df.groupby(['animal']).mean())
print("-"*15)
print("层次索引:可以使用level参数对分层索引的不同级别进行分组")
# 层次索引:可以使用level参数对分层索引的不同级别进行分组
arrays = [
['Falcon', 'Falcon', 'Parrot', 'Parrot'], # falcon:猎鹰
['Captive', 'Wild', 'Captive', 'Wild'] # 俘虏,囚徒,战俘
]
index = pd.MultiIndex.from_arrays(arrays,names=('animal','type'))
df_two = pd.DataFrame({'max speed':[390,350,30,20]},index=index)
print(df_two)
print(df_two.groupby(level=0).mean())
print(df_two.groupby(level='type').mean())
print("-"*15)
print("可以通过设置dropna参数来选择是否在主键中包含NA,默认设置为True")
# 可以通过设置dropna参数来选择是否在主键中包含NA,默认设置为True
l = [[1,2,3],[1,None,4],[2,1,3],[1,2,2]]
df_three = pd.DataFrame(l,columns=["a","b","c"])
print(df_three)
print("~"*10)
print(df_three.groupby(by=["b"]).sum())
print("~"*10)
print(df_three.groupby(by=["b"],dropna=False).sum())
print("~"*10)
print("-"*15)
#结果:
animal max speed
0 falcon 380
1 falcon 370
2 parrot 24
3 parrot 26
max speed
animal
falcon 375
parrot 25
---------------
层次索引:可以使用level参数对分层索引的不同级别进行分组
max speed
animal type
Falcon Captive 390
Wild 350
Parrot Captive 30
Wild 20
max speed
animal
Falcon 370
Parrot 25
max speed
type
Captive 210
Wild 185
---------------
可以通过设置dropna参数来选择是否在主键中包含NA,默认设置为True
a b c
0 1 2.0 3
1 1 NaN 4
2 2 1.0 3
3 1 2.0 2
~~~~~~~~~~
a c
b
1.0 2 3
2.0 2 5
~~~~~~~~~~
a c
b
1.0 2 3
2.0 2 5
NaN 1 4
5.DataFrame.nunique()获得行或者列重复的个数
nunique(axis=0,dropna = True):计算指定轴中不同元素的数量。返回具有不同元素数量的序列。可以忽略NAN值。
axis | {0 或‘index’,1 或’columns‘},默认0,要使用的轴。0 或’index’表示行,1或’columns’表示列 |
dropna | 布尔值,默认为True。不要在计数中包含NAN |
返回值 | Series |
df = pd.DataFrame({'A': [4, 5, 6], 'B': [4, 1, 1]})
print("df\n",df)
print("df.nunique\n",df.nunique())
print("df.nuique(axis=1)\n",df.nunique(axis=1))
结果:
df:
A B
0 4 4
1 5 1
2 6 1
df.nunique:
A 3
B 2
dtype: int64
df.nuique(axis=1):
0 1
1 2
2 2
dtype: int64
三、时间相关
pandas中有4个和时间相关的一般概念
- 日期时间:具有时区支持的特定日期和时间。类似于datetime.datetime标准库
- 时间增量:绝对持续时间。类似于datetime.timedelta标准库
- 时间跨度:由时间点及其相关频率定义的时间跨度
- 日期偏移量:来自dateutil包的dateutil.relativedelta.relativedelta相似
日期时间 | to_datetime 或者date_range |
时间增量 | to_timedelta或者timedelta_range |
时间跨度 | Period 或者period_range |
日期偏移 | DateOffset |
3. DataFrame.tz_convert()
4. DataFrame.tz_localize()
四、查询相关
1.DataFrame.query()
2.DataFrame.where()
3.DataFrame.at()
4.DataFrame.loc()
5.DataFrame.iloc()
五、数据格式转换
1.dataframe.to_dict()
2.DataFrame.to_sql()
3.DataFrame.read_sql()
六、连表查询相关
1. DataFrame.merge()
dataframe.merge(right,how=‘inner’,on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=False,suffixes=(‘_x’,‘_y’),copy=True,indicator=False,validate=None):将DataFrame或命名的Series对象与数据库样式的连接合并。命名的Series对象被视为具有单个命名列的DataFrame。连接是在列或索引上完成的。如果在列上连接列,DataFrame索引将被忽略。否则,如果加入索引上的索引或列上的索引,则索引将被传递。执行交叉合并时,不允许合并列规范。
注意:
如果两个键列都包含键为空值的行,则这些行将相互匹配。这与通常的SQL连接行行为不同,并可能导致意外结果。
right | DataFrame或命名的Series,即要合并的对象 |
how | {‘left’,‘right’,‘outer’,‘inner’,‘cross’},默认‘inner’,要执行的合并类型。left:仅使用来自左边frame的键,并保留键的顺序;right:仅使用来自右边frame的键,并保留键的顺序;outer:使用两个frame的并集,按字典顺序对键进行排序;inner:使用两个frame的交集,保留左键的顺序;cross:使用两个frame创建笛卡尔积,保留左键的顺序 |
on | 标签或列表。要加入的列或索引级别名称。这些必须在两个dataframe中都可以找到。如果on是None并且不合并索引,则默认为两个dataframe中列的交集 |
left_on | 标签或列表或类似数组,要在左侧DataFrame中加入的列或索引级别名称。也可以是左侧DataFrame长度的数组或数组列表。这些数组被视为列 |
right_on | 标签或列表或类似数组,要在右侧DataFrame中加入的列或索引级别名称。也可以是右侧DataFrame长度的数组或数组列表。这些数组被视为列。 |
left_index | 布尔值,默认为False。使用左侧dataframe中的索引作为连接键。如果是MultiIndex,则另一dataframe中的键数(索引或列数)必须与级别数匹配 |
right_index | 布尔值,默认为False。使用右侧dataframe中的索引作为连接键 |
sort | 布尔值,默认为False,在结果dataframe中按字典顺序对连接键进行排序。如果为False,则连接键的顺序取决于连接类型(how关键字) |
suffixes | |
copy | 布尔值,默认为True。如果为False,请尽可能避免复制 |
indicator | |
validate | str,可选。如果指定,则检查合并是否属于指定类型。“one_to_one"或"1:1”:检查合并键在左右数据集中是否唯一;“one_to_many"或"1:m”:检查合并键在左侧数据集中是否唯一;“many_to_one"或"m:1”:检查合并建在右边的数据集中是否唯一 |
df1 = pd.DataFrame({'lkey': ['foo', 'bar', 'baz', 'foo'],
'value': [1, 2, 3, 5]})
df2 = pd.DataFrame({'rkey': ['foo', 'bar', 'baz', 'foo'],
'value': [5, 6, 7, 8]})
print("df1\n",df1)
print("df2\n",df2)
# 在 lkey 和 rkey 列上合并df1 和 df2。值列附加了默认后缀 _x 和 _y。
df3 = pd.merge(df1,df2,left_on='lkey',right_on='rkey')
print("df3\n",df3)
# 合并DataFrames df1 和 df2,并在任何重叠列上附加指定的左右后缀。
df4 = pd.merge(df1,df2,left_on='lkey',right_on='rkey',suffixes=('_left','_right'))
print("df4\n",df4)
# 合并DataFrames df1 和 df2,但如果 DataFrames 有任何重叠列,则会引发异常。
# df4 = pd.merge(df1, df2, left_on='lkey', right_on='rkey', suffixes=(False,False))
test1 = pd.DataFrame({'a': ['foo', 'bar'], 'b': [1, 2]})
test2 = pd.DataFrame({'a': ['foo', 'baz'], 'c': [3, 4]})
print("test1\n",test1)
print("test2\n",test2)
test3=pd.merge(test1,test2,on='a',how='inner')
print("test3\n",test3)
test4 = pd.merge(test1,test2,on='a',how='left')
print("test4\n",test4)
# 笛卡尔积
data1 = pd.DataFrame({'left': ['foo', 'bar']})
data2 = pd.DataFrame({'right': [7, 8]})
print("data1\n",data1)
print("data2\n",data2)
data3 = pd.merge(data1,data2,how="cross")
print("data3\n",data3)
结果:
df1
lkey value
0 foo 1
1 bar 2
2 baz 3
3 foo 5
df2
rkey value
0 foo 5
1 bar 6
2 baz 7
3 foo 8
df3
lkey value_x rkey value_y
0 foo 1 foo 5
1 foo 1 foo 8
2 foo 5 foo 5
3 foo 5 foo 8
4 bar 2 bar 6
5 baz 3 baz 7
df4
lkey value_left rkey value_right
0 foo 1 foo 5
1 foo 1 foo 8
2 foo 5 foo 5
3 foo 5 foo 8
4 bar 2 bar 6
5 baz 3 baz 7
test1
a b
0 foo 1
1 bar 2
test2
a c
0 foo 3
1 baz 4
test3
a b c
0 foo 1 3
test4
a b c
0 foo 1 3.0
1 bar 2 NaN
data1
left
0 foo
1 bar
data2
right
0 7
1 8
data3
left right
0 foo 7
1 foo 8
2 bar 7
3 bar 8
2.DataFrame.join()
dataframe.join(other,on=None,how=‘left’,lsuffix=‘’,rsuffix=‘’,sort=False):
在索引或键列上将列与其他dataframe连接。通过传递一个列表,一次有效的按索引连接多个dataframe对象。
other | :DataFrame、Series或DataFrame列表。索引应该类似于这一列中的一列。如果传递了Series,则必须设置其name属性,并将其用作生成的DataFrame中的列名 |
on | :字符串、字符串列表或类似数组的情况,可选字段。调用者中的列或 |
how | :{‘left’,‘right’,‘outer’,‘inner’},默认‘left’。表示如何处理这两个对象的操作。left:使用调用框架的索引(或指定的列);right:使用other的索引;outer:将调用框架的索引(如果指定了on,则为列)与其他索引形成联合,并对其进行排序。按字典顺序;inner:形成调用框架的索引(或指定了on的列)与其他索引的交集,保留调用的索引的顺序;cross:从两个帧创建笛卡尔积,保留左键的顺序。 |
lsuffix | :从左框架的重叠列中使用的后缀 |
rsuffix | :从右框架的重叠列中使用的后缀 |
sort | :布尔值,默认为False。通过连接键按字典顺序对结果DataFrame进行排序。如果为False,则连接键的顺序取决于连接类型(how 关键字) |
返回值 | 包含来自调用者和其他列的DataFrame |
3. DataFrame.concat()
七、处理每个元素相关
1.DataFrame.apply()
2.DataFrame.applymap()
八、具体应用场景相关
1. dataframe中按照某一列的值将其他列合并
方法一:
data = {
"uuid":[1,2,3,2,1],
"fruit":["apple","peach","pear","watermelon","banana"]
}
df = pd.DataFrame(data)
print(df)
uuid_list = []
for index,row in df.iterrows():
in_dict = {}
if row['uuid'] not in uuid_list:
uuid_list.append(row['uuid'])
test = [{x:list()} for x in uuid_list]
print(test)
for index, row in df.iterrows():
key = row['uuid']
for each in test:
for k,v in each.items():
if k == key:
each[k].append(row['fruit'])
print(test)
#结果:
df:
uuid fruit
0 1 apple
1 2 peach
2 3 pear
3 2 watermelon
4 1 banana
test:
[{1: []}, {2: []}, {3: []}]
test:
[{1: ['apple', 'banana']}, {2: ['peach', 'watermelon']}, {3: ['pear']}]
方法二:
import pandas as pd
import numpy as np
# 读入数据
test_df = {
"姓名": ["张三","张三","张三","李四","李四","李四","王五","王五","赵六","赵六"],
"爱好": ["旅游","画画","游泳","跳舞","打羽毛球","唱歌","打羽毛球","唱歌","旅游","唱歌"],
"性别": ["男","男","男","女","女","女","男","男","女","女"]
}
df = pd.DataFrame(test_df)
print("df:")
print(df)
# 定义拼接函数,并对字段进行去重
def concat_func(x):
return pd.Series({
'爱好': x['爱好'].unique(),
'性别': x['性别'].unique()
})
# 分组聚合+拼接
result = df.groupby(df['姓名']).apply(concat_func).reset_index()
# 结果展示
print("result:")
print(result)
#结果:
df:
姓名 爱好 性别
0 张三 旅游 男
1 张三 画画 男
2 张三 游泳 男
3 李四 跳舞 女
4 李四 打羽毛球 女
5 李四 唱歌 女
6 王五 打羽毛球 男
7 王五 唱歌 男
8 赵六 旅游 女
9 赵六 唱歌 女
result:
姓名 爱好 性别
0 张三 [旅游, 画画, 游泳] [男]
1 李四 [跳舞, 打羽毛球, 唱歌] [女]
2 王五 [打羽毛球, 唱歌] [男]
3 赵六 [旅游, 唱歌] [女]
2.dataframe中一列数据为list时分成多列或多行
参考:方法来源于该博客
from copy import deepcopy
def split_col(data, column):
"""拆分成列
:param data: 原始数据
:param column: 拆分的列名
:type data: pandas.core.frame.DataFrame
:type column: str
"""
data = deepcopy(data)
max_len = max(list(map(len, data[column].values))) # 最大长度
new_col = data[column].apply(lambda x: x + [None]*(max_len - len(x))) # 补空值,None可换成np.nan
new_col = np.array(new_col.tolist()).T # 转置
for i, j in enumerate(new_col):
data[column + str(i)] = j
return data
def split_cols(data, columns):
"""批量拆分成列并且不要原始列
:param data: 原始数据
:param columns: 拆分的列名
:type data: pandas.core.frame.DataFrame
:type columns: list
"""
for c in columns:
new_col = data.pop(c)
max_len = max(list(map(len, new_col.values))) # 最大长度
new_col = new_col.apply(lambda x: x + [None] * (max_len - len(x))) # 补空值,None可换成np.nan
new_col = np.array(new_col.tolist()).T # 转置
for i, j in enumerate(new_col):
data[c + str(i)] = j
return data
def split_row(data, column):
"""拆分成行
:param data: 原始数据
:param column: 拆分的列名
:type data: pandas.core.frame.DataFrame
:type column: str
"""
row_len = list(map(len, data[column].values))
rows = []
for i in data.columns:
if i == column:
row = np.concatenate(data[i].values)
else:
row = np.repeat(data[i].values, row_len)
rows.append(row)
return pd.DataFrame(np.dstack(tuple(rows))[0], columns=data.columns)
if __name__=="__main__":
data ={
'name':['小明','小红'],
'hobby':[["running","swimming"],["sking","joging","drawing"]],
"pet":[["dog","cat"],["rabbit","monkey","tiger"]]
}
df = pd.DataFrame(data)
df_col = split_cols(df,["hobby","pet"])
df_row = split_row(df,column="hobby")
结果:
df:
name hobby pet
0 小明 [running, swimming] [dog, cat]
1 小红 [sking, joging, drawing] [rabbit, monkey, tiger]
df_col:
name hobby0 hobby1 hobby2 pet0 pet1 pet2
0 小明 running swimming None dog cat None
1 小红 sking joging drawing rabbit monkey tiger
df_row:
name hobby pet
0 小明 running [dog, cat]
1 小明 swimming [dog, cat]
2 小红 sking [rabbit, monkey, tiger]
3 小红 joging [rabbit, monkey, tiger]
4 小红 drawing [rabbit, monkey, tiger]
3.dataframe中将两列数据相减,得到第三列数据
def x(a, b):
d1 = datetime.datetime.strptime(str(a), '%Y-%m-%d %H:%M:%S')
d2 = datetime.datetime.strptime(str(b), '%Y-%m-%d %H:%M:%S')
delta = d1 - d2
# 相减得到秒数,转化为小时,并四舍五入保留两位小数round(x,2)
return round((delta.total_seconds() / 3600),2)
test_dict={
"a":["2021-12-21 10:00:00","2022-04-07 12:00:00"],
"c":["2021-12-21 11:30:00","2022-04-07 13:00:00"]
}
df = pd.DataFrame(test_dict)
print(df)
df['c-a'] = df.apply(lambda f: x(f['c'], f['a']), axis=1)
print(df)
结果:
a c
0 2021-12-21 10:00:00 2021-12-21 11:30:00
1 2022-04-07 12:00:00 2022-04-07 13:00:00
a c c-a
0 2021-12-21 10:00:00 2021-12-21 11:30:00 1.5
1 2022-04-07 12:00:00 2022-04-07 13:00:00 1.0
4.用dataframe.filter()过滤掉多余的数据列,减少数据量
dataframe.filter(items=None,like=None,regex=None,axis=None):根据指定的索引标签过滤dataframe的行或列
items | list | 保留项目中的轴标签 |
like | str | 保留“like in label”的标签 |
regex | str | 正则表达式,保留re.search(regex,label)轴的标签 |
axis | {0或index,1 或 columns}默认为None |
test_data = {
"name": ["小蓝", "小红", "小绿"],
"hobby": ["swim", "run", "jog"],
"age": [10, 6, 7]
}
df = pd.DataFrame(test_data,index=['one','two','three'])
结果:
df=
name hobby age
one 小蓝 swim 10
two 小红 run 6
three 小绿 jog 7
df.filter(items=['name', 'age'])=
name age
one 小蓝 10
two 小红 6
three 小绿 7
df.filter(regex='y$', axis=1)=
hobby
one swim
two run
three jog
df.filter(like='e',axis=0)
name hobby age
one 小蓝 swim 10
three 小绿 jog 7
5.dataframe修改index,columns名的方法
一般常用的两个方法:
- 使用
DataFrame.index=[newName],DataFrame.columns=[newNew]
- 使用
DataFrame.rename()方法
DataFrame.rename(mapper=None,index=None,columns=None,axis=None,copy=True,inplace=False,level=None)
mapper、index、columns | 可以任选其一使用,可以是将index和columns结合使用,index 和column直接传入mapper或者字典的形式 |
axis | {0 或index,1 或columns},默认为index |
copy | boolean,默认为True,是否复制基础数据 |
inplace | boolean,默认为False,是否返回新的dataframe,如果为True,忽略复制值 |
test_data = {
"name": ["小红", "小蓝", "小紫", "小粉"],
"age": [5, 6, 7, 9],
"hobby": ["swimming", "running", "joging","playing the piano"]
}
df = pd.DataFrame(test_data)
print("orign df:\n",df)
name age hobby
0 小红 5 swimming
1 小蓝 6 running
2 小紫 7 joging
3 小粉 9 playing the piano
df.index = ["one", "two", "three","four"]
print("df:\n",df)
df:
name age hobby
one 小红 5 swimming
two 小蓝 6 running
three 小紫 7 joging
four 小粉 9 playing the piano
# 使用map方法进行映射
df.index = df.index.map(str.upper)
print("df:\n",df)
df:
name age hobby
ONE 小红 5 swimming
TWO 小蓝 6 running
THREE 小紫 7 joging
FOUR 小粉 9 playing the piano
# 使用rename,可以分别为index 和 column 来指定值
df1 = df.rename(index=str.lower,columns=str.upper) # 这种方法是产生一个新dataframe
print("df1:\n", df1)
df1:
NAME AGE HOBBY
one 小红 5 swimming
two 小蓝 6 running
three 小紫 7 joging
four 小粉 9 playing the piano
# rename 还可以传入字典
df2 = df1.rename(index={'two':2},columns={'NAME':'姓名'})
print("df2:\n", df2)
df2:
姓名 AGE HOBBY
one 小红 5 swimming
2 小蓝 6 running
three 小紫 7 joging
four 小粉 9 playing the piano
# rename 使用自定义的map 函数
def test_map(x):
return "zh"+x
print(df1.index.map(test_map))
Index(['zhone', 'zhtwo', 'zhthree', 'zhfour'], dtype='object')
print("df1:\n",df1.rename(index=test_map))
df1:
NAME AGE HOBBY
zhone 小红 5 swimming
zhtwo 小蓝 6 running
zhthree 小紫 7 joging
zhfour 小粉 9 playing the piano
6.dataframe中按照某一列进行排序
- dataframe.sort_values(by, axis=0, ascending=True, inplace=False, kind=‘quicksort’, na_position=‘last’, ignore_index=False, key=None):按任一轴上的值排序
by | str 或 列表,要排序的名称或名称列表。如果轴为 0 或“索引”,则by可能包含索引级别和/或列标签。如果轴为 1 或“列”,则by可能包含列级别和/或索引标签 |
axis | {0 或 ‘index’,1 或 ‘columns’},默认 0。要排序的轴 |
ascending | bool 或 bool 列表,默认 True |
升序与降序排序。指定多个排序顺序的列表。如果这是一个布尔列表,则必须匹配 by 的长度。 | |
kind | {‘quicksort’, ‘mergesort’, ‘heapsort’, ‘stable’},默认 ‘quicksort’。排序算法的选择。合并排序和稳定是唯一稳定的算法。对于 DataFrame,此选项仅在对单个列或标签进行排序时应用 |
na_position | {‘first’,‘last’},默认’last’。如果first ,则将 NaNs 放在开头;最后将 NaN 放在最后。 |
ignore_index | 布尔值,默认为 False。如果为 True,则生成的轴将标记为 0、1、…、n - 1。 |
key | 可调用,可选在排序之前将键函数应用于值。这类似于内置函数中的keysorted()参数,显着的区别是这个key函数应该是矢量化的。它应该期望 a Series并返回一个与输入具有相同形状的系列。它将独立应用于by中的每一列 |
data={
"name": ["小红", "小蓝", "小粉"],
"score": [64, 26, 77]
}
df = pd.DataFrame(data)
print(df)
df.sort_values(by="score", ascending=False, inplace=True)
print(df)
结果:
df:
name score
0 小红 64
1 小蓝 26
2 小粉 77
after_sort_df:
name score
2 小粉 77
0 小红 64
1 小蓝 26
df = pd.DataFrame({
"time": ['0hr', '128hr', '72hr', '48hr', '96hr'],
"value": [10, 20, 30, 40, 50]
})
print(df)
time value
0 0hr 10
1 128hr 20
2 72hr 30
3 48hr 40
4 96hr 50
df.sort_values(
by="time",
key=lambda x: np.argsort(index_natsorted(df["time"]))
)
print(df)
time value
0 0hr 10
3 48hr 40
2 72hr 30
4 96hr 50
1 128hr 20
- dataframe.rank(axis=0, method=‘average’, numeric_only=NoDefault.no_default, na_option=‘keep’, ascending=True, pct=False):沿轴计算数值数据等级s(1 到 n)。默认情况下,为相等的值分配一个排名,该排名是这些值排名的平均值。
axis | {0 或 ‘index’,1 或 ‘columns’},默认 0 |
直接排名的索引 | |
method | 方法{‘average’, ‘min’, ‘max’, ‘first’, ‘dense’},默认 ‘average’ |
如何对具有相同值(即平局)的记录组进行排名:average:组的平均排名;min:组中的最低排名;max:组中的最高排名;first:按照它们在数组中出现的顺序分配的rank;dense:像’min’,但组间排名总是增加1。 | |
na_option | {‘keep’,‘top’,‘bottom’},默认’keep’。如何对NaN 值进行排名:keep:将 NaN等级分配给 NaN 值;top:为 NaN 值分配最低等级;botom:将最高等级分配给 NaN 值 |
numeric_only | 布尔值,可选。对于 DataFrame 对象,如果设置为 True,则仅对数字列进行排名。 |
ascending | 升序布尔值,默认 True。元素是否应按升序排列。 |
pct | 布尔值,默认为 False。是否以百分位形式显示返回的排名。 |
返回值:与调用者相同的类型,返回具有数据等级s 作为值的 Series 或 DataFrame。 |
x = {"name": ["张三", "李四", "王五", "赵六"],
"scores": [60, 40, 50, 40]}
df = pd.DataFrame(x)
print(df)
df["排名"] = df["sales"].rank(method="dense", ascending=False)
结果:
orgin_df:
name scores
0 张三 60
1 李四 40
2 王五 50
3 赵六 40
rank_df:
name scores 排名
0 张三 60 1.0
1 李四 40 3.0
2 王五 50 2.0
3 赵六 40 3.0
7. 行列转置
方法一:
df = pd.DataFrame({"姓名":["张三","张三","张三","李四","李四","李四","王五","王五","王五"],"科目":["数学","语文","英语","数学","语文","英语","数学","语文","英语"],"成绩":[90,89,79,91,92,97,90,89,87]})
print("df")
print(df)
df1 = df.set_index(['姓名','科目'])['成绩']
print("df1")
print(df1)
df2 = df1.unstack().fillna(0)
print("df2")
print(df2)
df3 = df2.rename_axis(columns=None)
print("df3")
print(df3)
df4 = df3.reset_index()
print("df4")
print(df4)
结果:
df
姓名 科目 成绩
0 张三 数学 90
1 张三 语文 89
2 张三 英语 79
3 李四 数学 91
4 李四 语文 92
5 李四 英语 97
6 王五 数学 90
7 王五 语文 89
8 王五 英语 87
df1
姓名 科目
张三 数学 90
语文 89
英语 79
李四 数学 91
语文 92
英语 97
王五 数学 90
语文 89
英语 87
Name: 成绩, dtype: int64
df2
科目 数学 英语 语文
姓名
张三 90 79 89
李四 91 97 92
王五 90 87 89
df3
数学 英语 语文
姓名
张三 90 79 89
李四 91 97 92
王五 90 87 89
df4
姓名 数学 英语 语文
0 张三 90 79 89
1 李四 91 97 92
2 王五 90 87 89
- pd.set_index()
(1) 将一列作为索引
(2)设置复合索引
(3)设置复合索引源码 - pd.unstack()
- pd.fillna()
- pd.rename_axis()
- pd.reset_index()
- pd.pivot()
方法二:
df = pd.DataFrame({"姓名":["张三","张三","张三","李四","李四","李四","王五","王五","王五"],"科目":["数学","语文","英语","数学","语文","英语","数学","语文","英语"],"成绩":[90,89,79,91,92,97,90,89,87]})
df6 = pd.pivot(df,index='姓名',columns='科目',values='成绩').rename_axis(columns=None).reset_index().fillna(0)
print("df6")
print(df6)
结果:
df6
姓名 数学 英语 语文
0 张三 90 79 89
1 李四 91 97 92
2 王五 90 87 89
8.分组并得到每组的值
df = pd.DataFrame({"动物":["dog","rabbit","cat","dog"],"食物":["apple","carrot","fish","meat"]})
final =[]
for table,item in df.groupby('动物'):
print(table)
temp={}
temp[table]=[]
for index,row in item.iterrows():
temp[table].append(row['食物'])
final.append(temp)
print(final)
结果:
cat
dog
rabbit
[{'cat': ['fish']}, {'dog': ['apple', 'meat']}, {'rabbit': ['carrot']}]