0
点赞
收藏
分享

微信扫一扫

【python数据分析(13)】Pandas中数据去重与替换、数据分组(groupby方法的使用)、分组统计方法(基本函数及扩展)


1. 去重及替换

1.1 ​​.duplicated()​​ 方法,判断是否重复

可以通过布尔判断,得到不重复的值(类比之前的​​.is_unique()​​方法)

s = pd.Series([1,1,1,2,2,3,4,5])
print(s.duplicated())
print(s[s.duplicated() == False])

–> 输出的结果为:

0    False
1 True
2 True
3 False
4 True
5 False
6 False
7 False
dtype: bool

0 1
3 2
5 3
6 4
7 5
dtype:

1.2 ​​drop.duplicates()​​移除重复

★★★★★ ​​inplace​​​参数:是否替换原值,默认​​False​​(也就是不改变原来数据的值)

这里特别容易出错,有 两种方式 可以改变原来的数据,一种是通过inplace参数,还有一种是重新赋值(这里容易搞混)

s.drop_duplicates(inplace = True)
print(s)

s = s.drop_duplicates()
print(s)

–> 输出的结果为:(注意上面的操作,一个是赋值了,一个是没有赋值,在使用​​inplace=True​​时候,不用赋值)

0    1
3 2
5 3
6 4
7 5
dtype: int64

0 1
3 2
5 3
6 4
7 5
dtype:

Dataframe中使用duplicated(上面对于Series的操作都适用于DataFrame,因为里面的的任意一列单独拿出来都是一个Series)

df = pd.DataFrame({'key1':['a','a',3,4,5],
'key2':['a','a','b','b','c']})
print(df.duplicated())
print(df['key2'].duplicated())
print(df['key2'].drop_duplicates())

–> 输出的结果为:

0    False
1 True
2 False
3 False
4 False
dtype: bool

0 False
1 True
2 False
3 True
4 False
Name: key2, dtype: bool

0 a
2 b
4 c
Name: key2, dtype: object

★★★★★1.3 替换

​.replace()​​​ 方法 在进行DataFrame数据微调的时候经常使用(可以和之前的删除数据​​del 列名​​进行类比)

可一次性替换一个值或多个值,也可传入列表或字典

s = pd.Series(list('ascaazsd'))
print(s.replace('a', np.nan))
print(s.replace(['a','s'] ,np.nan))
print(s.replace({'a':'hello world!','s':123}))

–> 输出的结果为:

0    NaN
1 s
2 c
3 NaN
4 NaN
5 z
6 s
7 d
dtype: object

0 NaN
1 NaN
2 c
3 NaN
4 NaN
5 z
6 NaN
7 d
dtype: object

0 hello world!
1 123
2 c
3 hello world!
4 hello world!
5 z
6 123
7 d
dtype: object

2. 数据分组

分组统计 - groupby功能

​df.groupby​​(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)

Dataframe在行(axis=0)或列(axis=1)上进行分组,将一个函数应用到各个分组并产生一个新值,然后函数执行结果被合并到最终的结果对象中。

2.1 groupby对象

1) 直接分组得到一个​​groupby​​对象(可迭代),是一个中间数据,没有进行计算

df = pd.DataFrame({'X' : ['A', 'B', 'A', 'B'], 'Y' : [1, 4, 3, 2]})
print(df)
print(df.groupby('X'))
print(type(df.groupby('X'))

–> 输出的结果为:

0  A  1
1 B 4
2 A 3
3 B 2
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x10C1F890>
<class 'pandas.core.groupby.generic.DataFrameGroupBy'>

2) 迭代的对象组成​​list​​列表就可以进行索引、也可以对列表进行遍历循环输出

print(list(df.groupby('X')))
print(list(df.groupby('X'))[0])
for n,g in df.groupby('X'):
print(n)
print(g)
print('——————')

–> 输出的结果为:(从结果可以看出,迭代器里面的元素是以元祖的方式存放的,第一个是组名(分组后的标签名),第二个就是组内的数据DataFrame)

[('A',    X  Y
0 A 1
2 A 3), ('B', X Y
1 B 4
3 B 2)]

('A', X Y
0 A 1
2 A 3)

A
X Y
0 A 1
2 A 3
——————
B
X Y
1 B 4
3 B 2

3) ​​.get_group()​​ 提取分组后的组内数据DataFrame

print(df.groupby(['X']).get_group('A'),'\n')
print(df.groupby(['X']).get_group('B'),'\n')

–> 输出的结果为:

0  A  1
2 A 3

X Y
1 B 4
3 B 2

4) ​​.groups​​​:将分组后的groups转为​​dict​​,可以字典索引方法来查看groups里的元素

grouped = df.groupby(['X'])
print(grouped.groups)
print(grouped.groups['A'])
print(grouped.groups['A'].values)

–> 输出的结果为:(注意这里存在着pandas的版本问题,只是数据显示的问题,可以通过​​.values​​方式转换)

#老版本会输出下面内容
{'B': [1, 3], 'A': [0, 2]}
[0, 2]

#新版本会输出下面内容(pandas版本1.0.1)
{'A': Int64Index([0, 2], dtype='int64'), 'B': Int64Index([1, 3], dtype='int64')}
Int64Index([0, 2], dtype='int64')

#添加.values的方式就可以获得和原来一样的数据类型
[0 2]

5) ​​.size()​​:查看分组后的长度

sz = grouped.size()
print(sz,type(sz))

–> 输出的结果为:(这一步的输出是基于上一步分组后的结果)

X
A 2
B 2
dtype: int64 <class 'pandas.core.series.Series'>

2.2 按照多列进行分组

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar','foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
'C' : np.random.randn(8),
'D' : np.random.randn(8)})
grouped = df.groupby(['A','B']).groups
print(df)
print(grouped)
print(grouped[('foo', 'three')])

–> 输出的结果为:

0  foo    one -0.668695  0.247781
1 bar one -0.125374 2.259134
2 foo two -0.112052 1.618603
3 bar three -0.098986 0.150488
4 foo two 0.912286 -1.260029
5 bar two 1.096757 -0.571223
6 foo one -0.090907 -1.671482
7 foo three 0.088176 -0.292702

#老版本输出结果
{('bar', 'two'): [5], ('foo', 'two'): [2, 4], ('bar', 'one'): [1], ('foo', 'three'): [7], ('bar', 'three'): [3], ('foo', 'one'): [0, 6]}
[7]

#新版本输出如下
{('bar', 'one'): Int64Index([1], dtype='int64'), ('bar', 'three'): Int64Index([3], dtype='int64'), ('bar', 'two'): Int64Index([5], dtype='int64'), ('foo', 'one'): Int64Index([0, 6], dtype='int64'), ('foo', 'three'): Int64Index([7], dtype='int64'), ('foo', 'two'): Int64Index([2, 4], dtype='int64')}
Int64Index([7], dtype='int64')

2.3 按照值类型分列

其他轴上的分组 ,通过改变​​axis​​的参数完成

df = pd.DataFrame({'data1':np.random.rand(2),
'data2':np.random.rand(2),
'key1':['a','b'],
'key2':['one','two']})
print(df)
print(df.dtypes)
for n,p in df.groupby(df.dtypes, axis=1):
print(n)
print(p)
print('——————')

–> 输出的结果为:

0  0.418399  0.540522    a  one
1 0.903899 0.960402 b two

data1 float64
data2 float64
key1 object
key2 object
dtype: object

float64
data1 data2
0 0.418399 0.540522
1 0.903899 0.960402
——————
object
key1 key2
0 a one
1

2.4 通过字典或者Series分组

mapping中,a、b列对应的为one,c、d列对应的为two,以字典来分组(e的存在不影响)

df = pd.DataFrame(np.arange(16).reshape(4,4),
columns = ['a','b','c','d'])
print(df)
mapping = {'a':'one','b':'one','c':'two','d':'two','e':'three'}
by_column = df.groupby(mapping, axis = 1)
print(by_column.sum())

–> 输出的结果为:(要想分组之后产生我们需要的数据,需要添加一些方法,比如这里的​​.sum()​​汇总)

0   0   1   2   3
1 4 5 6 7
2 8 9 10 11
3 12 13 14 15

one two
0 1 5
1 9 13
2 17 21
3 25 29

s中,index中a、b对应的为one,c、d对应的为two,以Series来分组

s = pd.Series(mapping)
print(s,'\n')
print(s.groupby(s).count())

–> 输出的结果为:(自动按照Series的值进行分组,选择以​​.count()​​方式统计)

a      one
b one
c two
d two
e three
dtype: object

one 2
three 1
two 2
dtype:

2.5 通过函数分组

比如这里按照​​len​​(字母长度)分组

df = pd.DataFrame(np.arange(16).reshape(4,4),
columns = ['a','b','c','d'],
index = ['abc','bcd','aa','b'])
print(df,'\n')
print(df.groupby(len).sum())

–> 输出的结果为:(这里的len默认是对标签index使用的,选择以​​.sum()​​进行统计)

0   1   2   3
bcd 4 5 6 7
aa 8 9 10 11
b 12 13 14 15

a b c d
1 12 13 14 15
2 8 9 10 11
3 4 6 8 10

3. 分组统计方法

上面的示例中已经使用到了一些分组统计的方法,比如​​.sum()​​​,​​.count()​​等方法,下面介绍常用的统计方法

3.1 常用的统计方法

唯一索引用​​.groupby(level=0)​​,将同一个index的分为一组

s = pd.Series([1, 2, 3, 10, 20, 30], index = [1, 2, 3, 1, 2, 3])
grouped = s.groupby(level=0)
print(grouped,'\n')
print(s)

–> 输出的结果为:(第一个输出就是​​groupby​​ (迭代) 对象)

<pandas.core.groupby.generic.SeriesGroupBy object at 0x115276F0>

1 1
2 2
3 3
1 10
2 20
3 30
dtype:

1) 非NaN的第一个值

print(grouped.first(),'→ first:非NaN的第一个值')

–> 输出的结果为:

1    1
2 2
3 3
dtype:

2) 非NaN的最后一个值

print(grouped.last(),'→ last:非NaN的最后一个值\n')

–> 输出的结果为:

1    10
2 20
3 30
dtype:

3) 非NaN的和

print(grouped.sum(),'→ sum:非NaN的和\n')

–> 输出的结果为:

1    11
2 22
3 33
dtype: int64 sum:非NaN的和

4) 非NaN的平均值

print(grouped.mean(),'→ mean:非NaN的平均值\n')

–> 输出的结果为:

1     5.5
2 11.0
3 16.5
dtype:

5) 非NaN的算术中位数

print(grouped.median(),'→ median:非NaN的算术中位数\n')

–> 输出的结果为:

1     5.5
2 11.0
3 16.5
dtype:

6) 非NaN的值

print(grouped.count(),'→ count:非NaN的值\n')

–> 输出的结果为:

1    2
2 2
3 2
dtype:

7)非NaN的最小值、最大值

print(grouped.min(),'→ min、max:非NaN的最小值、最大值\n')

–> 输出的结果为:

1    1
2 2
3 3
dtype: int64 min、max:非NaN的最小值、最大值

8) 非NaN的标准差和方差

print(grouped.std(),'→ std,var:非NaN的标准差和方差\n')

–> 输出的结果为:

1     6.363961
2 12.727922
3 19.091883
dtype:

9) 非NaN的积

print(grouped.prod(),'→ prod:非NaN的积\n'

–> 输出的结果为:

1    10
2 40
3 90
dtype:

3.2 多函数计算:​​agg()​

★★★★★函数写法可以用​​str​​​,或者​​np.​​​方法;可以通过​​list​​​,​​dict​​​传入,当用​​dict​​​时,​​key​​​名为​​columns​

df = pd.DataFrame({'a':[1,1,2,2],
'b':np.random.rand(4),
'c':np.random.rand(4),
'd':np.random.rand(4),})
print(df)
print(df.groupby('a').agg(['mean',np.sum]))
print(df.groupby('a')['b'].agg({'result1':np.mean,
'result2':np.sum}))

–> 输出的结果为:

0  1  0.093550  0.988628  0.481633
1 1 0.389688 0.068360 0.371444
2 2 0.412428 0.232056 0.740094
3 2 0.320511 0.393042 0.891658

b c d
mean sum mean sum mean sum
a
1 0.241619 0.483238 0.528494 1.056988 0.426539 0.853077
2 0.366470 0.732939 0.312549 0.625099 0.815876 1.631752

result1 result2
a
1 0.241619 0.483238
2 0.366470 0.732939

3.3 分组转换及一般性

“拆分-应用-合并” ,主要是​​merge​​​ / ​​transform​​​ / ​​apply​​方法的使用

1) 数据分组转换

df = pd.DataFrame({'data1':np.random.rand(5),
'data2':np.random.rand(5),
'key1':list('aabba'),
'key2':['one','two','one','two','one']})
print(df)

–> 输出的结果为:

0  0.241148  0.215440    a  one
1 0.554391 0.765252 a two
2 0.920091 0.216041 b one
3 0.201641 0.869712 b two
4 0.961804 0.430776

按照key1分组求均值,进行合并

k_mean = df.groupby('key1').mean()
print(k_mean)
print(pd.merge(df,k_mean,left_on='key1',right_index=True).add_prefix('mean_'))

–> 输出的结果为:(通过分组、合并,得到一个包含均值的Dataframe,其中​​.add_prefix('mean_')​​:添加前缀)

0.585781  0.470489
b 0.560866 0.542877

mean_data1_x mean_data2_x mean_key1 mean_key2 mean_data1_y mean_data2_y
0 0.241148 0.215440 a one 0.585781 0.470489
1 0.554391 0.765252 a two 0.585781 0.470489
4 0.961804 0.430776 a one 0.585781 0.470489
2 0.920091 0.216041 b one 0.560866 0.542877
3 0.201641 0.869712 b two 0.560866 0.542877

按照key2分组求均值,字符串不能进行计算

print(df.groupby('key2').mean())
print(df.groupby('key2').transform(np.mean))

–> 输出的结果为:(data1、data2每个位置元素取对应分组列的均值,和原数据的标签​​index​​相对应)

0.209669  0.381341
two 0.206753 0.898320

data1 data2
0 0.209669 0.381341
1 0.206753 0.898320
2 0.209669 0.381341
3 0.206753 0.898320
4 0.209669 0.381341

2)一般化Groupby方法:​​apply(函数)​

★★★★★属于进阶的方法,一般可以节省很多代码量完成复杂的工作,但是掌握有一定的难度,apply后面多函数(常见就是lambda表达式),调用其功能

比如:直接查看描述分组后的统计量(​​.describe()​​方法)

df = pd.DataFrame({'data1':np.random.rand(5),
'data2':np.random.rand(5),
'key1':list('aabba'),
'key2':['one','two','one','two','one']})
print(df)
print(df.groupby('key1').apply(lambda x: x.describe()))

–> 输出的结果为:

0  0.873000  0.751742    a  one
1 0.934280 0.386892 a two
2 0.847525 0.779258 b one
3 0.513672 0.467257 b two
4 0.489208 0.822993 a one

data1 data2
key1
a count 3.000000 3.000000
mean 0.357638 0.553313
std 0.225001 0.407336
min 0.101986 0.185609
25% 0.273682 0.334385
50% 0.445378 0.483161
75% 0.485464 0.737165
max 0.525550 0.991168
b count 2.000000 2.000000
mean 0.544131 0.745138
std 0.525377 0.016776
min 0.172633 0.733276
25% 0.358382 0.739207
50% 0.544131 0.745138
75% 0.729879 0.751070
max 0.915628 0.757001

除使用lambda函数外,还可以自定义函数,如下

def f_df1(d,n):
return(d.sort_index()[:n])
#f_df1函数:返回排序后的前n行数据

def f_df2(d,k1):
return(d[k1])
# f_df2函数:返回分组后表的k1列,结果为Series,层次化索引

print(df.groupby('key1').apply(f_df1,2))
print(df.groupby('key1').apply(f_df2,'data2'))
print(type(df.groupby('key1').apply(f_df2,'data2')))

–> 输出的结果为:

0  0.373092  0.473234    a  one
1 0.777516 0.784485 a two
b 2 0.214563 0.007377 b one
3 0.452728 0.741134 b two

key1
a 0 0.473234
1 0.784485
4 0.626037
b 2 0.007377
3 0.741134
Name: data2, dtype: float64

<class 'pandas.core.series.Series'>


举报

相关推荐

0 条评论