首页 > 解决方案 > 使用 ipywidgets 绘制子集 Pandas 数据框

问题描述

我想pandas使用下拉菜单绘制数据框的子集ipywidgets,但我遇到了一些奇怪的错误。

import ipywidgets as wg
from IPython.display import display
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Make Data Frame
#
df = pd.DataFrame({
    
    "x": np.arange(32),
    "y": np.arange(32),
    "A": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    "B": [0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1],
    "C": [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1]
})

# Make dropdown menus
#
w1 = wg.Dropdown(
    options=[0,1],
    value=0,
    description='A:',
)
#
w2 = wg.Dropdown(
    options=[0,1],
    value=0,
    description='B:',
)
#
w3 = wg.Dropdown(
    options=[0,1],
    value=0,
    description='C:',
)
#
w4 = wg.Dropdown(
    options=['df'],
    value='df',
    description='DF:',
)

# Define plotting function
#
def myPlot(df, a, b, c):
    print(df)
    print(a)
    print(b)
    print(c)
    x = df["x"][df["A"]==a & df["B"]==b & df["C"]==c]
    y = df["y"][df["A"]==a & df["B"]==b & df["C"]==c]   
    plt.scatter(x,y)
    plt.show()

# Plot with interactive dropdown menus
#
wg.interact(myPlot, df=w4, a=w1, b=w2, c=w3)

当我尝试x在绘图函数中定义时发生错误:TypeError: string indices must be integers. 我认为这与将数据框放入绘图函数有关,因为绘图函数中的print命令为我提供了正确的 , 值,A但会打印字符串。BCdf

获得我想要的情节的方法是什么?

标签: pythonpandasmatplotlibplotipywidgets

解决方案


我不会尝试使用字符串从命名空间中提取变量。

我会包装你的交互器并直接传递数据框:

import ipywidgets as wg
from IPython.display import display
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt


# Make Data Frame
#
df = pd.DataFrame({
    "x": np.arange(32),
    "y": np.arange(32),
    "A": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
    "B": [0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1],
    "C": [0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1]
})

# Make dropdown menus
#
w1 = wg.Dropdown(
    options=[0,1],
    value=0,
    description='A:',
)
#
w2 = wg.Dropdown(
    options=[0,1],
    value=0,
    description='B:',
)
#
w3 = wg.Dropdown(
    options=[0,1],
    value=0,
    description='C:',
)


# Define plotting function
#
def myPlot(df, a, b, c):
    subset = df.loc[df["A"].eq(a) & df["B"].eq(b) & df["C"].eq(c), :]
    fig, ax = plt.subplots()
    ax.scatter("x", "y", data=subset)
    return fig


def interactive_plotter(df):
    df_widget = wg.fixed(df)
    return wg.interact(myPlot, df=df_widget, a=w1, b=w2, c=w3)

fig = interactive_plotter(df)

另一件事是要考虑的是您的链式逻辑语句:

逻辑运算符的运算顺序不是很直观

这个说法:

x = df["x"][df["A"]==a & df["B"]==b & df["C"]==c]

被评估为:

x = df["x"][df["A"] == (a & df["B"]) == (b & df["C"]==c)]

(或类似的东西)。

你想要的,至少,是这样的:

x = df["x"][(df["A"] == a) & (df["B"] == b) & (df["C"] == c)]

但我认为使用.loc访问器会更好:

x = df.loc[(df["A"] == a) & (df["B"] == b) & (df["C"] == c), "x"]

如果你不喜欢所有这些括号,你也可以使用.eq()

x = df.loc[df["A"].eq(a) & df["B"].eq(b) & df["C"].eq(c), "x"]

推荐阅读