【问题标题】:plotting a pandas dataframe column which contains NaN values绘制包含 NaN 值的 pandas 数据框列
【发布时间】:2018-11-02 10:28:08
【问题描述】:

我在将 pandas 数据框的第二列绘制到 twinx y 轴上时遇到了一些问题。我认为这可能是因为第二个有问题的列包含 NaN 值。 NaN 值之所以存在,是因为每 10 年只有一次数据可用,尽管第一列每年都有可用数据。它们是使用 np.nan 生成的,为了清楚起见,我将其包含在最后。

这里的直觉是将两个系列绘制在同一个 x 轴上,以显示它们随时间的趋势。

这是我的代码和数据框:

import pandas as pd
import numpy as np
import matplotlib as plt
import matplotlib.pyplot as plt

list1 = ['1297606', '1300760', '1303980', '1268987', '1333521', '1328570', 
         '1328112', '1353671', '1371285', '1396658', '1429247', '1388937', 
         '1359145', '1330414', '1267415', '1210883', '1221585', '1186039', 
         '884273', '861789', '857475', '853485', '854122', '848163', '839226', 
         '820151', '852385', '827609', '825564', '789217', '765651']

list1a = [1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 
          1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 
          2004, 2005, 2006, 2007, 2008, 2009, 2010]

list3b = [121800016.0, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, 
          145279588.0, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, 
          160515434.5, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, 
          168140487.0]

d = {'Year': list1a,'Abortions per Year': list1, 
     'Affiliation with Religious Institutions': list3b}
newdf = pd.DataFrame(data=d)

newdf.set_index('Year',inplace=True)

fig, ax1 = plt.subplots(figsize=(20,5))

y2min = min(newdf['Affiliation with Religious Institutions'])
y2max = max(newdf['Affiliation with Religious Institutions'])
ax1.plot(newdf['Abortions per Year'])
#ax1.set_xticks(newdf.index)
ax1b = ax1.twinx()
ax1b.set_ylim(y2min*0.8,y2max*1.2)
ax1b.plot(newdf['Affiliation with Religious Institutions'])
plt.show()

我最终得到了一个不显示第二个图的图表。 (当我将第二个图更改为具有每年的数值时,它会绘制它)。这是第二个图(带有 NaN 值)——被忽略:

感谢任何建议。

*如何为第二列生成 np.nan 值:我循环遍历索引列,并且对于没有数据的每一年,将 np.nan 返回到列表中,然后将其设为一列。

for i in range(len(list1a)):
    if list1a[i] in list3a:
        var = list2[j]
        list3b.append(var)

        j+=1
    else:
        var = np.nan
        list3b.append(var)

【问题讨论】:

  • @James 感谢您的编辑,我在打印时用 nan(不是 np.nan)粘贴了列表

标签: python pandas matplotlib nan


【解决方案1】:

我现在明白了。 要使用现有代码实现这一点,您只需使用 Pandas 前向填充。

紧接着

newdf.set_index('Year',inplace=True)

随便放

newdf.fillna(method='ffill', inplace=True)

【讨论】:

  • 亲爱的@GeorgeLPerkins,解决方案是准确的,但出于完全美观的目的,我喜欢折线图在数据点之间具有渐变的方式。
  • 啊,我明白了。渐变看起来确实比楼梯更令人愉悦。
【解决方案2】:

您可以使用pandas DataFrame 方法来完成大部分您正在做的事情。这两行将解决您的所有问题:

newdf = newdf.astype(float)
newdf = newdf.interpolate(method='linear')

因此您的绘图代码将如下所示:

fig, ax1 = plt.subplots(figsize=(20,5))

newdf = newdf.astype(float)
newdf = newdf.interpolate(method='linear')
y2min = newdf['Affiliation with Religious Institutions'].min()
y2max = newdf['Affiliation with Religious Institutions'].max()
newdf['Abortions per Year'].plot.line(ax=ax1)
#ax1.set_xticks(newdf.index)
ax1b = ax1.twinx()
ax1b.set_ylim(y2min*0.8,y2max*1.2)
newdf['Affiliation with Religious Institutions'].plot.line(ax=ax1b)
plt.show()

使用pandas 方法绘制DataFrame 只是一个建议。但你也可以使用matplotlib 代码,因为pandas 使用matplotlib 作为绘图后端

我添加的两行执行以下操作:
您的专栏Abortions per Year 属于dtype object。您需要将其转换为数字类型:

newdf = newdf.astype(float)

事实上,NaN-values 不会被忽略,但不会显示,因为它们是单个值。因此,您可以将marker 添加到第二个图中。如果要为第二个图显示一条线,则需要使用以下内容插入值:

newdf = newdf.interpolate(method='linear')

如果插值完成,标记可以被移除。

【讨论】:

  • 谢谢@Scotty 1-我要找的是两行。我应该使用哪个 newdf 转换?
  • 两者都做两件不同的事情。需要newdf = newdf.astype(float) 转换为float 格式以用于正确 绘图类型。如果您想使用newdf = newdf.interpolate(method='linear'),取决于您是否只希望在已知隶属关系的运动中使用标记,或者您是否想要绘制插值线。
  • 我更新了我的帖子,因此它包含了两种解决方案。
  • 非常感谢@Scotty1-,这非常有帮助
【解决方案3】:

两件事。您需要将Abortions per Year 列转换为数字类型以进行绘图,至少对于您提供的str 格式的数据;其次,您可以通过在绘图前删除nan 值将Affiliation with Religious Institutions 绘制为一条线。

ax1.plot(newdf['Abortions per Year'].astype(int))

...

ax1b.plot(newdf['Affiliation with Religious Institutions'].dropna())

【讨论】:

  • numpy 以及 pandas 的原则之一是:int 用于索引,float 用于数据。因此,您的第一行应该是:ax1.plot(newdf['Abortions per Year'].astype(float))
  • 数据的整数值是完全可以接受的。浮点运算的计算成本更高,因此将整数数据保留为整数是个好主意。
  • 只要你有小的值,这是真的。但是您永远不知道将执行哪些计算。考虑到此示例中使用的数字,最大约 1.68e8int 操作可能很关键。试试np.array(newdf.max().astype(int))**2np.array(newdf.max().astype(float))**2
  • 这就是原理的原因:int用于索引,float用于数据。没有人需要遵循它,它不是强制性的。但强烈推荐。就像 PEP 风格指南和 python 的禅宗一样。这不是强制性的,但确实有充分的理由遵循这些建议。
  • 你在哪里遇到过 pandas 或 numpy 的问题?
【解决方案4】:

这里出错的一个基本问题是您将一个点绘制为一条线。

list3b = [121800016.0,南,南....... 从一点到一无所有。

如果将第二个 nan 更改为一个值: list3b = [121800016.0, 121800016.0, 南, ..... 然后你会看到一个结果。

也许您应该将这些值绘制为条形或散点。

【讨论】:

  • 我想在这里得到的是所有存在的值之间的线。因此,对于第二列,每 10 年会有一条线连接每个点,而对于第一列,每一年都会有一条线连接这些点。
  • @ZakS:我发布了一个完全符合您要求的解决方案。
猜你喜欢
  • 2012-11-16
  • 2018-03-28
  • 1970-01-01
  • 2016-07-13
  • 2016-01-23
  • 1970-01-01
  • 2023-01-28
  • 1970-01-01
相关资源
最近更新 更多