当前位置: 首页 > news >正文

【pandas】17 数据处理和绘图

【pandas】17 数据处理和绘图

2023.1.16 pandas数据处理方法和绘图:读取数据、更改数据、时间数据等
主要参考:https://mofanpy.com/tutorials/data-manipulation/pandas/time

17.1运算方法

17.1.1 筛选赋值运算

  • 就是用前面的方法对数据进行筛选,然后对值进行一定的操作(对数据修改)

本章实例就是通过不同方法筛选出需要的位置,进行赋值

import pandas as pd
import numpy as np

data = np.arange(-12, 12).reshape((6, 4))
df = pd.DataFrame(
  data, 
  index=list("abcdef"), 
  columns=list("ABCD"))
df
ABCD
a-12-11-10-9
b-8-7-6-5
c-4-3-2-1
d0123
e4567
f891011
# 对A列*0操作
df["A"] *= 0
df
ABCD
a0-11-10-9
b0-7-6-5
c0-3-2-1
d0123
e0567
f091011
# 对(0,0),(1,0)位置重新导入值 用两种方法
# loc是索引,iloc是位置
df.loc['a','A']=100
df.iloc[1,0]=200
df
ABCD
a100-11-10-9
b200-7-6-5
c0-3-2-1
d0123
e0567
f091011
# 对a行都乘以2
df.iloc[0,:] *= 2
df
ABCD
a200-22-20-18
b200-7-6-5
c0-3-2-1
d0123
e0567
f091011
#对A列中是0的都选为1
df["A"][df["A"]==0]=1
df
ABCD
a200-22-20-18
b200-7-6-5
c1-3-2-1
d1123
e1567
f191011

17.1.2 apply

  • 数据.apply(方程式,。。):通过方程式的筛选选择,批量修改
df
ABCD
a200-22-20-18
b200-7-6-5
c1-3-2-1
d1123
e1567
f191011
# 做开2次方
df.apply(np.sqrt)
ABCD
a14.142136NaNNaNNaN
b14.142136NaNNaNNaN
c1.000000NaNNaNNaN
d1.0000001.0000001.4142141.732051
e1.0000002.2360682.4494902.645751
f1.0000003.0000003.1622783.316625
  • 通过一个方程 返回了第一列的两倍 ;第二列-1
def func(x):
    return x[0] * 2, x[1] * -1

df.apply(func, axis=1, result_type='expand')
01
a40022
b4007
c23
d2-1
e2-5
f2-9
df.iloc[0]
A    200
B    -22
C    -20
D    -18
Name: a, dtype: int32
  • result_type='expand':让输出的结果可以生成多 column。如下:
def func(x):
    return x[0] * 2, x[1] * -1

df.apply(func, axis=1)
a    (400, 22)
b     (400, 7)
c       (2, 3)
d      (2, -1)
e      (2, -5)
f      (2, -9)
dtype: object
  • 如果 reult_type="broadcast",那么原 column 和 index 名会继承到新生成的数据中;没有的话本例column0-3
  • 因为广播,这个return必须凑齐colunm个数,即使没变化,也要写上,不然报错
print("df:\n",df)

def func(x):
    return x[0] * 2, x[1] * -1,x[2] ,x[3] 
print("-----")
print(df.apply(func, axis=1, result_type='expand'))
df.apply(func, axis=1, result_type='broadcast')
df:
      A   B   C   D
a  200 -22 -20 -18
b  200  -7  -6  -5
c    1  -3  -2  -1
d    1   1   2   3
e    1   5   6   7
f    1   9  10  11
-----
     0   1   2   3
a  400  22 -20 -18
b  400   7  -6  -5
c    2   3  -2  -1
d    2  -1   2   3
e    2  -5   6   7
f    2  -9  10  11
ABCD
a40022-20-18
b4007-6-5
c23-2-1
d2-123
e2-567
f2-91011
def func(r):
    return r[2] * 4

last_row = df.apply(func, axis=0)
print("last_row:\n", last_row)

df.iloc[2, :] = last_row
print("\ndf:\n", df)
last_row:
 A    16
B   -48
C   -32
D   -16
dtype: int64

df:
      A   B   C   D
a  200 -22 -20 -18
b  200  -7  -6  -5
c   16 -48 -32 -16
d    1   1   2   3
e    1   5   6   7
f    1   9  10  11

注意:

  • 默认是对列进行操作,也就是 axis=1,是按行来操作的,是对每行的第3个数操作,所以输出你看这变化是
  • axis=0对列的第3个数操作,反而输出变化的是 这个别弄反了

17.2 文字处理

17.2.1 格式化字符

  • str.upper(); str.lower(); 全大写全小写
  • str.len():长度
  • str.strip(); str.lstrip(); str.rstrip()去掉两边空格。去掉左空格、有空格
  • str.split()数据用什么分割

我们用这些处理字符的时候,你要确保 Series 或者 DataFrame 的 dtype="string"

  • .dtype:看类型
  • .asdtype:改类型
pd_not_s = pd.Series(
    ["A", "B", "C", "Aaba", "Baca", "CABA", "dog", "cat"],
)
print("pd_not_s type:", pd_not_s.dtype)
pd_s = pd_not_s.astype("string")
print("pd_s type:", pd_s.dtype)
pd_not_s type: object
pd_s type: string

用法很简单,举几个简单的例子:

# 【例子1】全部大写
print("\npandas:\n", pd_s.str.upper())
pandas:
 0       A
1       B
2       C
3    AABA
4    BACA
5    CABA
6     DOG
7     CAT
dtype: string
#【例子2】每个字符串数据长度
print("\npandas len:\n", pd_s.str.len())
pandas len:
 0    1
1    1
2    1
3    4
4    4
5    4
6    3
7    3
dtype: Int64
# 【例子3】从新有需要的字符切割数据
py_s = ["a_b_c", "jill_jesse", "frank"]
pd_s = pd.Series(py_s, dtype="string")

print("\npandas split:\n", pd_s.str.split("_"))
pandas split:
 0        [a, b, c]
1    [jill, jesse]
2          [frank]
dtype: object
  • **【和python比较】**我们用python,一般形式是这样的(除了大小写)
print("python len:\n", [len(s) for s in py_s])
print("python split:\n", [s.split("_") for s in py_s])
python len:
 [5, 10, 5]
python split:
 [['a', 'b', 'c'], ['jill', 'jesse'], ['frank']]
# 加一个 result_type="expand",将拆分出来的结果放到不同的 column 中去
pd_s.str.split("_", expand=True)
012
0abc
1jilljesse<NA>
2frank<NA><NA>

17.2.2 正则方案

我们用 str.contains() str.match() 来确认它真的找到了匹配文字

  • str.contains() :有就识别出来
  • str.match():完全匹配

pattern = r"[0-9][a-z]"
s = pd.Series(["1", "1a", "11c", "abc"], dtype="string")
s.str.contains(pattern)
0    False
1     True
2     True
3    False
dtype: boolean
- ` r"[0-9][a-z]"`:这里面【条件1】【条件2】两个条件都要有。
- `11c`识别出来了`1c`,用`contains`是`True`,用`match`是`False`
s.str.match(pattern)
0    False
1     True
2    False
3    False
dtype: boolean

17.3 异常数据处理

17.3.1 找到NaN数据

pd.isna(), pd.notna()

import pandas as pd
import numpy as np

df = pd.DataFrame([[1, None],[np.nan, 4]])
df
01
01.0NaN
1NaN4.0
#找NaN数据
df.isna()
01
0FalseTrue
1TrueFalse

【找不是NaN数据】 df.notna()或者~df.isna()

df.notna()

01
0TrueFalse
1FalseTrue

17.3.2 处理NaN

  • df.dropna():移除
  • df.fillna():填充
  • df.clip():不符合范围的填充
df = pd.DataFrame({
    "a": [1, None, 3], 
    "b": [4, 5, 6]
})
df
ab
01.04
1NaN5
23.06
- 移除,**默认**是`axis=0`,列方向改变;
df.dropna()
ab
01.04
23.06
df.dropna(axis=1)
b
04
15
26
  • df.fillna():填充
# 在a标签上做了平均,这里排除掉了没有意义的值
a_mean = df["a"].mean()
new_col = df["a"].fillna(a_mean)
df["a"] = new_col
df
ab
01.04
12.05
23.06
  • 有规律的值,也可以做一些运算
# b是的4倍
df = pd.DataFrame({
    "a": [1, None, 3, None], 
    "b": [4, 8, 12, 12]
})
a_nan = df["a"].isna()
a_new_value = df["b"][a_nan] / 4
print("返回了索引和值:\n",a_new_value)


new_col = df["a"].fillna(a_new_value)
df["a"] = new_col
df
返回了索引和值:
 1    2.0
3    3.0
Name: b, dtype: float64
ab
01.04
12.08
23.012
33.012
`["b"][a_nan] / 4`:b中是NaN的值/4
  • df.clip():不符合范围的填充;

有些值大的离谱小的离谱,这些超出的值会给一个上下的阈值

df = pd.DataFrame({
    "a": [1, 1, 2, 1, 2, 40, 1, 2, 1],
})
df["a"] = df["a"].clip(lower=0, upper=3)
df
a
01
11
22
31
42
53
61
72
81

17.4 时间数据

17.4.1 读时间序列

  • pd.to_datetime():pandas数据中有时间,但是它不知道是时间序列 所以要转换一下
import pandas as pd

df = pd.DataFrame({
    "time": ["2022/03/12", "2022/03/13", "2022/03/14"],
    "value": [1,2,3]
})
print(df)
         time  value
0  2022/03/12      1
1  2022/03/13      2
2  2022/03/14      3
# 这一列 是时间序列
pd.to_datetime(df["time"])
0   2022-03-12
1   2022-03-13
2   2022-03-14
Name: time, dtype: datetime64[ns]
  • 任意形式都可以,个性化识别format

    • 所有前面都加个%如%% 比配一个 %;%S 是秒
    • 比如喜欢用 月@日@年%%秒|时|分
pd.to_datetime(
    [
        "1@21@2022%%11|11|32", 
        "12@01@2022%%44|02|2", 
        "4@01@2022%%14|22|2"
    ],
    format="%m@%d@%Y%%%%%S|%H|%M"
)
DatetimeIndex(['2022-01-21 11:32:11', '2022-12-01 02:02:44',
               '2022-04-01 22:02:14'],
              dtype='datetime64[ns]', freq=None)

17.4.2 自建时间序列datetime

  1. 【类似于range】:pd.date_range(start, end)
  • freq="48h":间隔时间。(没有)默认是一天
import datetime

# 设置成时间序列 默认是年月日
start = datetime.datetime(2022, 3, 12)
end = datetime.datetime(2022, 3, 18)

index = pd.date_range(start, end, freq="48h")
index
DatetimeIndex(['2022-03-12', '2022-03-14', '2022-03-16', '2022-03-18'], dtype='datetime64[ns]', freq='48H')
  • periods=:从开始到结束 平均去几个值
print("\n\npd.date_range(start, end, periods=5)\n",
    pd.date_range(start, end, periods=5)
)
pd.date_range(start, end, periods=5)
 DatetimeIndex(['2022-03-12 00:00:00', '2022-03-13 12:00:00',
               '2022-03-15 00:00:00', '2022-03-16 12:00:00',
               '2022-03-18 00:00:00'],
              dtype='datetime64[ns]', freq=None)

17.4.3 选取时间data_range

  1. 做了一个在时间上随机生成正态分布的值

start = datetime.datetime(2022, 3, 1)
end = datetime.datetime(2022, 3, 23)

rng = pd.date_range(start, end)
ts = pd.Series(np.random.randn(len(rng)), index=rng)

ts
2022-03-01    0.471139
2022-03-02   -1.101305
2022-03-03   -0.544299
2022-03-04    1.244004
2022-03-05   -1.594690
2022-03-06    1.686098
2022-03-07   -0.613820
2022-03-08   -2.399893
2022-03-09    1.132414
2022-03-10   -1.198595
2022-03-11    0.779643
2022-03-12    0.265703
2022-03-13   -0.545246
2022-03-14    1.518926
2022-03-15    0.255980
2022-03-16    0.876557
2022-03-17   -0.599384
2022-03-18   -0.351991
2022-03-19    0.033286
2022-03-20    0.085700
2022-03-21    0.421871
2022-03-22   -1.981706
2022-03-23    0.209435
Freq: D, dtype: float64
  • index=rng 这里面把时间放在了index上
  1. 在这个时间序列下,可以利用各种方式 切片,直接输入等来取一些值
#可分片
ts[1:8].plot()
<AxesSubplot:>

在这里插入图片描述

import datetime

t1 = datetime.datetime(2022, 3, 12)
t2 = datetime.datetime(2022, 3, 18)
ts[t1: t2].plot()
<AxesSubplot:>

在这里插入图片描述

ts["2022-03-12": "2022-03-18"].plot()
<AxesSubplot:>

在这里插入图片描述

17.4.4 时间运算pd.Timedelta .dayofyear .strftime

  1. 比如我想复制一份这周的表格,给下周用, 我就直接将这个月 copy 过来,然后日期上加一周时间。
  • Timedelta 是一种用于时间加减的时间单位
rng = pd.date_range("2022-01-01", "2022-01-07")
rng + pd.Timedelta(weeks=1)
DatetimeIndex(['2022-01-08', '2022-01-09', '2022-01-10', '2022-01-11',
               '2022-01-12', '2022-01-13', '2022-01-14'],
              dtype='datetime64[ns]', freq='D')
 `weeks`参数,还可以用 `days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds` 这些
  • 算这是今年第几天.dayofyear
import pandas as pd
rng = pd.date_range("2022-2-08","2022-2-14")
rng.dayofyear
Int64Index([39, 40, 41, 42, 43, 44, 45], dtype='int64')

除此之外,还有:rng.dayofweek; rng.weekofyear; rng.weekday

  • .strftime:输出形式切换
rng.strftime("%m/%d/%Y")
Index(['02/08/2022', '02/09/2022', '02/10/2022', '02/11/2022', '02/12/2022',
       '02/13/2022', '02/14/2022'],
      dtype='object')
  • .day_name(); .month_name():看是周几或者那个月
rng.day_name()
Index(['Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday',
       'Monday'],
      dtype='object')

17.4.5 时区

  • .tz_localize:时区初始化
#方法1 
s = pd.to_datetime(
    ["2022/03/12 22:11", "2022/03/12 12:11", "2022/03/12 2:11"]
)
s_us = s.tz_localize("America/New_York")
s_us
DatetimeIndex(['2022-03-12 22:11:00-05:00', '2022-03-12 12:11:00-05:00',
               '2022-03-12 02:11:00-05:00'],
              dtype='datetime64[ns, America/New_York]', freq=None)
# 方法2 在创建时间数据时候
rng = pd.date_range(
    "2022-01-08", "2022-01-11", 
    tz="America/New_York")
rng
  • .tz_convert:时区转换
s_cn = s_us.tz_convert("Asia/Shanghai")
s_cn
DatetimeIndex(['2022-03-13 11:11:00+08:00', '2022-03-13 01:11:00+08:00',
               '2022-03-12 15:11:00+08:00'],
              dtype='datetime64[ns, Asia/Shanghai]', freq=None)

17.5 绘制图表

  • 散点图 scatter
  • 折线图 plot
  • 条形图 .plot.bar()
  • 分布图 .plot.hist()
  • 饼图 plot.Pie
  • 面积图 plot.area

用法就是 df.图片名字.什么图

17.5.1 散点图Scatter

  • c: 对于这组数据中每个(x,y)数据点的颜色值
  • s: 画点的大小(size)
  • alpha:不透明度
  • cmap:colormap,你可以在这里找到非常丰富的案例.我这里觉得应该是选哪个调色板或色彩格式
import numpy as np
import pandas as pd

n = 10    # data size
df = pd.DataFrame({
    "x": np.random.normal(0, 1, n),
    "y": np.random.normal(0, 1, n), 
})
#color = np.arctan2(df["y"], df["x"])
df.plot.scatter(x="x", y="y", c=color, s=60, alpha=.5, cmap="rainbow")
<AxesSubplot:xlabel='x', ylabel='y'>

在这里插入图片描述

17.5.2 散点图 plot.Scatter()

n = 20    # data size
x = np.linspace(-1, 1, n)
y1 = x * -1 - 0.1 + np.random.normal(0, 0.3, n)
y2 = x * 2 + 0.4 + np.random.normal(0, 0.3, n)
df = pd.DataFrame({
    "x": x,
    "y1": y1,
    "y2": y2, 
})
df.plot(x="x", y=["y1", "y2"], alpha=.9)
<AxesSubplot:xlabel='x'>

在这里插入图片描述

更改的地方:透明度改成了9

17.5.3 条形图Bar

df = pd.DataFrame(np.random.rand(5, 3), columns=["a", "b", "c"])
print(df)
df.plot.bar()
          a         b         c
0  0.768000  0.963485  0.460891
1  0.824841  0.599105  0.607710
2  0.372849  0.541759  0.114071
3  0.278834  0.283976  0.661167
4  0.570884  0.638697  0.581616





<AxesSubplot:>

在这里插入图片描述

  • 放一起看stacked=True
df.plot.bar(stacked=True)
<AxesSubplot:>

在这里插入图片描述

  • .plot.barh()横竖轴调换
df.plot.barh()
<AxesSubplot:>

在这里插入图片描述

17.5.4 分布图 plot.hist()

分布图在机器学习和统计学中非常重要,我经常画分布图,比如要画 神经网络的参数分布可视化。 又或者是 GAN 生成对抗网络当中的数据分布。

df = pd.DataFrame(
    {
        "a": np.random.randn(1000) + 1,
        "b": np.random.randn(1000),
        "c": np.random.randn(1000) - 4,
    }
)

df.plot.hist(alpha=0.3, bins=60)
<AxesSubplot:ylabel='Frequency'>

在这里插入图片描述

bins 柱状体的数量

17.5.5 饼图plot.Pie

df = pd.DataFrame(
    {
        "bigBoss": np.random.rand(4),
        "smallBoss": np.random.rand(4),
    },
    index=["meeting", "supervise", "teaching", "team building"], 
)
df.plot.pie(subplots=True, figsize=(9,9), legend=False)
array([<AxesSubplot:ylabel='bigBoss'>, <AxesSubplot:ylabel='smallBoss'>],
      dtype=object)

在这里插入图片描述

subplots=True, figsize=(9,9), legend=False:

  • 这里是两组数据,要加subplots,是分开画意思;
  • legend 是用来确定要不要输出图例的。也就是有个图 来说什么颜色代表什么

17.5.6面 积图plot.area()

df = pd.DataFrame(
    np.random.rand(10, 4), 
    columns=["a", "b", "c", "d"]
)
df.plot.area()

<AxesSubplot:>

在这里插入图片描述

如果你不想上下堆砌在一起观看,而是有统一的一个起点,那可以用这个参数 stacked=False

df.plot.area(stacked=False)
<AxesSubplot:>

在这里插入图片描述

相关文章:

  • 怎样将网站建设后台装到云上/百度大数据
  • 做网站买哪家的主机好/网址seo优化排名
  • 发布任务做任务赚钱网站/平台推广费用一般是多少
  • 烟台本地自己独立商城网站/品牌推广的三个阶段
  • 杭州做网站博客/联合早报 即时消息
  • 淄博网站制作培训/北京疫情最新情况
  • Redis缓存和数据库不一致性
  • k8s ingress概念和实践
  • 【论文速递】ECCV2022 - 开销聚合与四维卷积Swin Transformer_小样本分割
  • cmakelists例子
  • ES6学习笔记之箭头函数
  • d的更好C关闭ctfe的dup
  • 当青训营遇上码上掘金之主题四-攒青豆
  • javaEE 初阶 — 文件内容的读写
  • Linux chattr命令
  • #9文献学习--基于元强化学习的边缘计算快速自适应任务卸载
  • 一篇文章带你学完JavaScript基础知识,超全的JavaScript知识点总结
  • react受控组件和非受控组件区别