【问题标题】:Grouped Column Operations in Python using Pandas使用 Pandas 在 Python 中分组列操作
【发布时间】:2021-11-07 06:50:00
【问题描述】:

我有一个由 .csv 导入组成的数据框,其中包含 n 次试验。试验按带有标题的列排列(试验 1 的波长 1,试验 2 的波长 2 等)我们正在跟踪化学反应期间溶液随时间的吸收。您可以在链接中看到excel文件的SS。试验分为三组(糖的克数为 IDV,以 nm 为单位的吸光度为 DV)。对于每个试验:

  1. 我需要确定最大值和最小值是多少。这当然可以使用 max() 和 min() 来完成,但是当我们每 0.25 秒采样一次时,数据可能会很嘈杂,这意味着我必须对其进行平滑处理。我已经建立了一个函数来做到这一点。我们也可能只是每隔一秒采样一次,因为无论如何它会更流畅。
  2. 每组三个试验都需要绘制在同一张图上进行比较。 n 次试验将创建 n/3 个图表。

我来自 MATLAB 的中级背景。这也不是我在那里能弄明白的。

到目前为止我做了什么?

我试图从每个试验的标题中列出一个列表,然后使用for 循环使用df.column_name 命令遍历数据:

data = pd.read_csv('data.csv')
col_name = data.columns.values
print(col_name)
for i in col_name:
    print(data.col_name[i])

代码一直运行到第 4 行,它返回错误:AttributeError: 'DataFrame' object has no attribute 'col_name'。在这里,我想用波长1试验中的所有值制作一个系列或一组(无论这里叫什么),以绘制/操纵/等。值得注意的是,我已经让多个绘图和多行手动工作:但我想将其自动化,因为这是编码的重点。这是“手动”版本的四张图表之一:

import pandas as pd
import matplotlib.pyplot as plt
#import matplotlib as matplotlib
data = pd.read_csv('data.csv')

plt.close("all")

n_rows = 2
n_columns = 2

#initialize figure
figure_size = (30,15)
font_size = 13
f, ([plt1, plt2], [plt3, plt4]) = plt.subplots(n_rows,n_columns, figsize = figure_size)

#plot first three runs 
x=data.time1
y=data.wavelength1
plt1.plot(x,y, label='Trial 1')
x=data.time2
y=data.wavelength2
plt1.plot(x,y,label='Trial 2')
plt1.set_title('0.3g Glucose', fontweight="bold", size=font_size)
x=data.time3
y=data.wavelength3
plt1.plot(x,y,label='Trial 3')
plt1.set_ylabel('Wavelength (nm)', fontsize = font_size)
plt1.set_xlabel('Time (s)', fontsize = font_size)
plt1.legend(fontsize=font_size)

我的第一个想法就是去做:

for i in range (0,num_col):
    plot(time,data.wavelength(i))

但这不起作用。我敢肯定这是一件很简单的事情,但它让我无法理解。

示例数据:

https://ufile.io/ac226vma

提前致谢! [1]:https://i.stack.imgur.com/gMtBN.png

【问题讨论】:

  • 代替data.col_name[i]试试data[col_name[i]]
  • Johan 有一个有趣的想法,但它也不起作用:``` for i in col_name: print(data[col_name[i]]) ``` 返回:“IndexError: only integers 、切片 (:)、省略号 (...)、numpy.newaxis (None) 和整数或布尔数组是有效的索引"

标签: python pandas csv matplotlib


【解决方案1】:

分析

我需要确定最大值和最小值。

由于您想要每个试验中的最大值,并且每个试验由一列表示,您可以使用DataFrame.min() 来获取每列中的最小值。如果你想知道最小值的索引,你也可以输入 idxmin() 。与 max 相同的想法。

df = pd.read_csv("data.csv")

# Get max and min values
print("ANALYSIS OF MIN AND MAX VALUES")
analysis_df = pd.DataFrame()
analysis_df["min"] = df.min()
analysis_df["min_idx"] = df.idxmin()
analysis_df["max"] = df.max()
analysis_df["max_idx"] = df.idxmax()
print(analysis_df)

产生:

ANALYSIS OF MIN AND MAX VALUES
                min  min_idx    max  max_idx
wavelength1   801.0      120  888.0        4
wavelength2   809.0       85  888.0        1
wavelength3   728.0       96  837.0        1
wavelength4   762.0      114  864.0        3
wavelength5   785.0      115  878.0        2
wavelength6   747.0      118  866.0        1
wavelength7   748.0      119  851.0        3
wavelength8   776.0      113  880.0        0
wavelength9   812.0      112  900.0        0
wavelength10  770.0      110  863.0        1
wavelength11  759.0      100  858.0        0
wavelength12  787.0       91  876.0        0
wavelength13  756.0       66  862.0        2
wavelength14  809.0       70  877.0        1
wavelength15  828.0       62  866.0        0

绘图

每组三个试验都需要绘制在同一张图上进行比较。 n 次试验将创建 n/3 个图表。

如果你把它分解成几个较小的子问题,这会更容易。

首先,您需要列出所有列并将它们分成三组。我复制了代码来执行此操作from here

def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.zip_longest(fillvalue=fillvalue, *args)

现在,一旦我们有了一组三个列名,我们就需要获取与这些列关联的数据框中的值。此外,由于您的数据文件包含每次试验的不同数量的观察值,我们需要删除文件末尾的 NaN。

def get_trials(df, column_group_names):
    """Get columns from dataframe, dropping missing values."""
    column_group = df[list(column_group_names)]
    column_group = column_group.dropna(how='all')
    return column_group

现在,让我们结合这两个功能:

col_iterator = grouper(3, df.columns)
[...]
for column_group_names in col_iterator:
    column_group = get_trials(df, column_group_names)
    [...]

这将让我们以三组为一组循环遍历列,并单独绘制它们。由于我们已将其过滤为我们感兴趣的数据,因此我们可以使用 DataFrame.plot 将其绘制到 matplotlib 图中。

接下来,我们需要遍历子图。在循环组的同时这样做有点烦人,所以我喜欢定义一个迭代器。

def subplot_axes_iterator(n_rows, n_columns):
    for i in range(n_rows):
        for j in range(n_columns):
            yield i, j

使用示例:

>>> list(subplot_axes_iterator(2, 2))
[(0, 0), (0, 1), (1, 0), (1, 1)]

现在,将这些部分组合起来:

# Plot data
n_rows = 2
n_columns = 3
figure_size = (15, 10)
font_size = 13
fig, axes = plt.subplots(n_rows, n_columns, figsize=figure_size)

col_iterator = grouper(3, df.columns)
axes_iterator = subplot_axes_iterator(n_rows, n_columns)
plot_names = [
    "Group 1",
    "Group 2",
    "Group 3",
    "Group 4",
    "Group 5",
]

for column_group_names, axes_position, plot_name in \
        zip(col_iterator, axes_iterator, plot_names):
    print(f"plotting {column_group_names} at {axes_position}")
    column_group = get_trials(df, column_group_names)
    column_group.plot(ax=axes[axes_position])
    axes[axes_position].set_title(plot_name, fontweight="bold", size=font_size)
    axes[axes_position].set_xlabel("Time (s)", fontsize=font_size)
    axes[axes_position].set_ylabel("Wavelength (nm)", fontsize=font_size)
plt.tight_layout()
plt.show()

(顺便说一句,你说要4张图,但是贴出来的数据集有15次试验,所以我做了5张图。)

最终脚本

(包括在内以方便复制/粘贴。)

import pandas as pd
import matplotlib.pyplot as plt
import itertools


def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.zip_longest(fillvalue=fillvalue, *args)


def get_trials(df, column_group_names):
    """Get columns from dataframe, dropping missing values."""
    column_group = df[list(column_group_names)]
    column_group = column_group.dropna(how='all')
    return column_group


def subplot_axes_iterator(n_rows, n_columns):
    for i in range(n_rows):
        for j in range(n_columns):
            yield i, j



df = pd.read_csv("data.csv")

# Get max and min values
print("ANALYSIS OF MIN AND MAX VALUES")
analysis_df = pd.DataFrame()
analysis_df["min"] = df.min()
analysis_df["min_idx"] = df.idxmin()
analysis_df["max"] = df.max()
analysis_df["max_idx"] = df.idxmax()
print(analysis_df)


# Plot data
n_rows = 2
n_columns = 3
figure_size = (15, 10)
font_size = 13
fig, axes = plt.subplots(n_rows, n_columns, figsize=figure_size)

col_iterator = grouper(3, df.columns)
axes_iterator = subplot_axes_iterator(n_rows, n_columns)
plot_names = [
    "Group 1",
    "Group 2",
    "Group 3",
    "Group 4",
    "Group 5",
]

for column_group_names, axes_position, plot_name in \
        zip(col_iterator, axes_iterator, plot_names):
    print(f"plotting {column_group_names} at {axes_position}")
    column_group = get_trials(df, column_group_names)
    column_group.plot(ax=axes[axes_position])
    axes[axes_position].set_title(plot_name, fontweight="bold", size=font_size)
    axes[axes_position].set_xlabel("Time (s)", fontsize=font_size)
    axes[axes_position].set_ylabel("Wavelength (nm)", fontsize=font_size)
plt.tight_layout()
plt.show()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    • 2021-04-19
    • 1970-01-01
    • 2015-09-12
    • 2021-01-22
    相关资源
    最近更新 更多