Py学习  »  JohanC  »  全部回复
回复总数  6
3 年前
回复了 JohanC 创建的主题 » Python Seaborn Ridge绘图教程不起作用

你可以替换 g.figure 具有 g.fig g、 身材 是同一变量的新名称。 refline() 是seaborn 0.11.2中的新版本(该网站假定您运行的是最新发布的版本)。你可以把电话换成 g.refline() 具有 g.map(plt.axhline, y=0, linewidth=2, linestyle="-", color=None, clip_on=False)

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

sns.set_theme(style="white", rc={"axes.facecolor": (0, 0, 0, 0)})

# Create the data
rs = np.random.RandomState(2022)
x = rs.randn(500)
g = np.tile(list("ABCDEFGHIJ"), 50)
df = pd.DataFrame(dict(x=x, g=g))
df["x"] += df["g"].map(ord)

# Initialize the FacetGrid object
pal = sns.cubehelix_palette(10, start=1, rot=-.25, light=.7)
g = sns.FacetGrid(df, row="g", hue="g", aspect=15, height=.5, palette=pal)

# Draw the densities in a few steps
g.map(sns.kdeplot, "x",
      bw_adjust=.5, clip_on=False,
      fill=True, alpha=1, linewidth=1.5)
g.map(sns.kdeplot, "x", clip_on=False, color="w", lw=2, bw_adjust=.5)

# passing color=None to refline() uses the hue mapping
# g.refline(y=0, linewidth=2, linestyle="-", color=None, clip_on=False)
g.map(plt.axhline, y=0, linewidth=2, linestyle="-", color=None, clip_on=False)

# Define and use a simple function to label the plot in axes coordinates
def label(x, color, label):
    ax = plt.gca()
    ax.text(0, .2, label, fontweight="bold", color=color,
            ha="left", va="center", transform=ax.transAxes)

g.map(label, "x")

# Set the subplots to overlap
g.fig.subplots_adjust(hspace=-.25)

# Remove axes details that don't play well with overlap
g.set_titles("")
g.set(yticks=[], xlabel="", ylabel="")
g.despine(bottom=True, left=True)
plt.show()

seaborn ridge plot example

下面是另一个使用flights数据集的示例:

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

sns.set_theme(style="white", rc={"axes.facecolor": (0, 0, 0, 0)})

flights = sns.load_dataset('flights')
pal = sns.cubehelix_palette(len(flights["year"].unique()), start=1.4, rot=-.25, light=.7, dark=.4)
g = sns.FacetGrid(flights, row="year", hue="year", aspect=20, height=.5, palette=pal)

g.map(sns.kdeplot, "passengers", bw_adjust=.6, cut=5, clip_on=False, fill=True, alpha=1, linewidth=1.5)
g.map(sns.kdeplot, "passengers", bw_adjust=.6, cut=5, clip_on=False, color="w", lw=2)
g.map(plt.axhline, y=0, linewidth=2, linestyle="-", color=None, clip_on=False)

def label(x, color, label):
    ax = plt.gca()
    ax.text(0, .1, label, fontweight="bold", color=color,
            ha="left", va="center", transform=ax.transAxes)

g.map(label, "year")
g.fig.subplots_adjust(hspace=-.7)
g.set(yticks=[], xlabel="", ylabel="", xlim=(None, 680), title="")
g.despine(bottom=True, left=True)
plt.show()

seaborn ridge plot flights dataset

目前尚不清楚您的数据是如何组织的,也不清楚您是如何创建表的。

假设输入数据有三列:“性别”、“问题”、“标记”。以下是该表格中的一些数据,以便进行测试:

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

df = pd.DataFrame({'gender': np.random.choice(['male', 'female', 'other'], 1000),
                   'question': pd.Categorical.from_codes(codes=np.random.randint(0, 10, 1000),
                                                         categories=[f'Q{i}' for i in range(1, 11)]),
                   'mark': np.random.randint(1, 6, 1000)})
df['gender'] = pd.Categorical(df['gender'], categories=['male', 'female', 'other'])  # fix an order

然后可以通过 df.pivot_table(index='gender', columns='question', values='mark') 并将其绘制为条形图,类似于问题的图像:

df.pivot_table(index='gender', columns='question', values='mark').plot.bar(rot=0, width=0.8)

pandas bar plot from pivot table

现在,以另一种方式创建pivot_表,将问题放置为x位置,将性别放置为颜色:

df.pivot_table(index='question', columns='gender', values='mark').plot.bar(rot=0, width=0.8)

pandas bar plot from transposed pivot table

如果已经创建了表格,则可以在打印前对其进行转置,这也会导致x轴出现问题:

df_table = df.pivot_table(index='gender', columns='question', values='mark')
df_table.T.plot.bar(rot=0, width=0.8)

另一种方法是使用seaborn,它直接从原始数据帧创建条形图,并且(可选)显示错误条(使用 ci=None 以抑制错误条)。你只需要告诉seaborn你想在x轴上看到什么,在y轴上看到什么,以及什么是彩色分离。

import seaborn as sns

ax = sns.barplot(data=df, x='question', y='mark', hue='gender')
ax.legend(bbox_to_anchor=[1.01, 1.01], loc='upper left')
plt.tight_layout()
plt.show()

sns.barplot using hue

现在,如果您的数据帧看起来像:

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

df = pd.DataFrame({'Gender': np.arange(3),
                   **{f'Q{i}': np.random.randint(15, 46, 3) / 10 for i in range(1, 11)}})

例如:

  Gender   Q1   Q2   Q3   Q4   Q5   Q6   Q7   Q8   Q9  Q10
0      0  3.9  2.7  2.2  2.6  2.2  2.8  2.2  3.2  2.9  2.9
1      1  4.2  2.0  4.4  2.4  3.6  2.1  1.6  4.0  2.7  4.2
2      2  3.7  3.9  4.2  2.9  3.2  4.4  4.2  2.1  2.9  3.6

您可以使用专有名称对“性别”列进行分类,将其用作索引,转换数据帧和绘图:

df['Gender'] = pd.Categorical.from_codes(df['Gender'], categories=['Male', 'Female', 'Other'])
df.set_index('Gender').T.plot.bar(rot=0, width=0.8)

您可以将字典转换为长格式的数据帧。然后用seaborn的 sns.catplot() 要绘制条形图的网格,请执行以下操作:

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

# first, create some test data with the given structure
mains = [*'ABCDEFGHIJKLMNOPQRST']
lengths = np.random.randint(2, 11, len(mains))
starts = np.append(0, lengths.cumsum())
D1 = {main: {f'X{i}': np.random.randint(2, 10) for i in range(s0, s1)}
      for main, s0, s1 in zip(mains, starts[:-1], starts[1:])}
D2 = {main: {f'X{i}': np.random.randint(2, 10) for i in range(s0, s1)}
      for main, s0, s1 in zip(mains, starts[:-1], starts[1:])}

# create a "long form" dataframe of the given dictionaries
df = pd.concat([pd.DataFrame({'Dictionary': ['D1'], 'main': [main], 'x': [x], 'Height': [val]})
                for main in D1.keys() for x, val in D1[main].items()] +
               [pd.DataFrame({'Dictionary': ['D2'], 'main': [main], 'x': [x], 'Height': [val]})
                for main in D2.keys() for x, val in D2[main].items()], ignore_index=True)

# draw a grid of barplots
g = sns.catplot(kind='bar', data=df, x='x', y='Height', hue='Dictionary', palette='spring',
                col='main', col_wrap=5, height=3, aspect=1.5, sharex=False)
g.set(xlabel='')  # remove superfluous x labels
plt.show()

sns.catplot grid of bar plots from dictionaries

3 年前
回复了 JohanC 创建的主题 » Python,小数之和

你可以创建一个替换字典。请注意,为了能够进行计算,需要将替换项写成数字,而不是字符串。一旦你有了号码表,你就可以打电话了 sum(list_of_numbers) .

下面是一些示例代码:

gene_code = "abcdef"
split_strings = [gene_code[i:i + 3] for i in range(0, len(gene_code), 3)]
replacements = {'abc': 1.2, 'def': 2.3}
numbers = [replacements[s] for s in split_strings]
print(sum(numbers))

如果某些字符串没有替换项,此代码将给出一个错误。您可以添加一个测试,并将这些数字替换为零:

numbers = [0 if not s in replacements else replacements[s]
           for s in split_strings]

注意,上面的代码使用 list comprehension .这样,一个循环,例如:

new_list = []
for item in old_list:
   new_list.append(func(item))

可以写成

new_list = [func(item) for item in old_list]

一旦你习惯了这种符号,你会发现它更容易阅读和维护。当你处理列表时,它会变得特别有用。

要从文件中读取:

replacements = {'abc': 1.2, 'def': 2.3}
with open("gene_codes.txt") as file:
    for gene_code in file.readlines():
        gene_code = gene_code.strip()
        # print(gene_code)
        split_strings = [gene_code[i:i + 3] for i in range(0, len(gene_code), 3)]
        numbers = [0 if not s in replacements else replacements[s]
                   for s in split_strings]
        print(sum(numbers))
3 年前
回复了 JohanC 创建的主题 » 在seaborn-python中的x轴上设置一个扭结

以下方法:

  • 隐藏 spine 表示现有的x轴
  • 为零添加一个虚拟点(例如在 x=40 )
  • 使用 clip_on=False 在主轴区域外绘制,以及 ax.get_xaxis_transform() 使用 "data coordinates" 对于 x 和“坐标轴” y ( 0 在底部和底部 1 在顶部);厚度和线条颜色是从脊椎复制的
  • 将虚拟零位显示为 0
import matplotlib.pyplot as plt
import numpy as np

data = np.random.randint(50, 89, 80)
bins = np.arange(50, data.max()+6, 5)
fig, ax = plt.subplots(figsize=(12,5))

ax.hist(data, bins=bins, fc='skyblue', ec='navy')
false_zero = bins[0] - 10
ax.set_xticks(np.append(false_zero, bins))
ax.set_xticklabels(np.append(0, bins))

for spine in ['top', 'right', 'bottom']:
    ax.spines[spine].set_visible(False)
ax.add_line(plt.Line2D(xdata=[false_zero, false_zero + 2, false_zero + 4, false_zero + 4, false_zero + 6, bins[-1] + 1],
                       ydata=[0, 0, 0.1, -0.1, 0, 0],
                       color=ax.spines['bottom'].get_edgecolor(), lw=ax.spines['bottom'].get_linewidth(),
                       clip_on=False, transform=ax.get_xaxis_transform()))
plt.tight_layout()
plt.show()

x axis with a kink

PS:对于原始帖子的纠结:

ax.add_line(plt.Line2D(xdata=[false_zero, false_zero + 2, false_zero + 2, false_zero + 6, false_zero + 6, bins[-1] + 1],
                       ydata=[0, 0, 0.1, -0.1, 0, 0], ...))

original kink

5 年前
回复了 JohanC 创建的主题 » python中的磁偶极子

这个 streamplot 返回包含两部分的容器对象“StreamplotSet”:

  • 线条:流线的线条集合
  • 箭头:包含FancyArrowPatch对象的PatchCollection(这些是三角形箭头)

c.lines.get_paths() 给出所有片段。通过迭代这些段,可以检查它们的顶点。当一段从上一段结束的地方开始时,两者都属于同一条曲线。请注意,每个线段都是一条短直线;许多线段一起用于形成流线型曲线。

下面的代码演示如何遍历这些段。为了显示正在发生的事情,每个段都被转换成一个二维点数组,适合于 plt.plot . 违约, plt.绘图

要查找一条特定曲线,可以将鼠标悬停在起点上,并注意该点的x坐标。然后测试代码中的坐标。例如,开始于 x=0.48 是以一种特殊的方式画出来的。

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import patches

def dipole(m, r, r0):
    R = np.subtract(np.transpose(r), r0).T
    norm_R = np.sqrt(np.einsum("i...,i...", R, R))
    m_dot_R = np.tensordot(m, R, axes=1)
    B = 3 * m_dot_R * R / norm_R**5 - np.tensordot(m, 1 / norm_R**3, axes=0)
    B *= 1e-7
    return B

X = np.linspace(-1, 1)
Y = np.linspace(-1, 1)

Bx, By = dipole(m=[0, 1], r=np.meshgrid(X, Y), r0=[-0.2,0.8])

plt.figure(figsize=(8, 8))
c = plt.streamplot(X, Y, Bx, By)
c.lines.set_visible(False)
paths = c.lines.get_paths()
prev_end = None
start_indices = []
for index, segment in enumerate(paths):
    if not np.array_equal(prev_end, segment.vertices[0]):  # new segment
        start_indices.append(index)
    prev_end = segment.vertices[-1]
for i0, i1 in zip(start_indices, start_indices[1:] + [len(paths)]):
    # get all the points of the curve that starts at index i0
    curve = np.array([paths[i].vertices[0] for i in range(i0, i1)] + [paths[i1 - 1].vertices[-1]])
special_x_coord = 0.48
for i0, i1 in zip(start_indices, start_indices[1:] + [len(paths)]):
    # get all the points of the curve that starts at index i0
    curve = np.array([paths[i].vertices[0] for i in range(i0, i1)] + [paths[i1 - 1].vertices[-1]])
    if abs(curve[0,0] - special_x_coord) < 0.01:  # draw one curve in a special way
        plt.plot(curve[:, 0], curve[:, 1], '-', lw=10, alpha=0.3)
    else:
        plt.plot(curve[:, 0], curve[:, 1], '.', ls='-')

plt.margins(0, 0)
plt.show()

resulting plot