【问题标题】:Understanding this Pandas script理解这个 Pandas 脚本
【发布时间】:2013-11-13 21:46:48
【问题描述】:

我收到此代码以将数据分组为直方图类型数据。我一直在尝试理解这个 pandas 脚本中的代码,以便对其进行编辑、操作和复制。对于我理解的部分,我有 cmets。

代码

import numpy as np
import pandas as pd


column_names = ['col1', 'col2', 'col3', 'col4', 'col5', 'col6', 
              'col7', 'col8', 'col9', 'col10', 'col11'] #names to be used as column labels.  If no names are specified then columns can be refereed to by number eg. df[0], df[1] etc.

df = pd.read_csv('data.csv', header=None, names=column_names) #header= None means there are no column headings in the  csv file

df.ix[df.col11 == 'x', 'col11']=-0.08 #trick so that 'x' rows will be grouped into a category >-0.1 and <= -0.05.  This will allow all of col11 to be treated as a numbers

bins = np.arange(-0.1, 1.0, 0.05) #bins to put col11 values in.  >-0.1 and <=-0.05 will be our special 'x' rows, >-0.05 and <=0 will capture all the '0' values.
labels = np.array(['%s:%s' % (x, y) for x, y in zip(bins[:-1], bins[1:])]) #create labels for the bins
labels[0] = 'x' #change first bin label to 'x'
labels[1] = '0' #change second bin label to '0'

df['col11'] = df['col11'].astype(float) #convert col11 to numbers so we can do math on them


df['bin'] = pd.cut(df['col11'], bins=bins, labels=False) # make another column 'bins' and put in an integer representing what bin the number falls into.Later we'll map the integer to the bin label


df.set_index('bin', inplace=True, drop=False, append=False) #groupby is meant to run faster with an index

def count_ones(x):
    """aggregate function to count values that equal 1"""
    return np.sum(x==1)

dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [count_ones, len]})
dfg.index = labels[dfg.index]

dfg.ix['x',('col11', 'mean')]='N/A'
print(dfg)
dfg.to_csv('new.csv')

我真正难以理解的部分在这个部分:

def count_ones(x):
    """aggregate function to count values that equal 1"""
    return np.sum(x==1)

dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [count_ones, len]})
dfg.index = labels[dfg.index]

dfg.ix['x',('col11', 'mean')]='N/A'
print(dfg)
dfg.to_csv('new.csv')

如果有人能够评论这个脚本,我将不胜感激。也可以随意更正或添加到我的 cmets 中(这些是我到目前为止所假设的,它们可能不正确)。我希望这对 SOF 来说不是太离题。我很乐意为任何可以帮助我的用户提供 50 点奖励。

【问题讨论】:

  • 首先阅读 agg 函数文档
  • 谢谢,到目前为止,我一直在看熊猫教程视频。
  • 我相信这也是他所指的文档。 pandas.pydata.org/pandas-docs/dev/groupby.html 恐怕我无法为 cmets 提供帮助,这段代码暂时超出了我的能力范围。
  • @Boud 原始 cmets 中有什么不正确的吗? (以防万一我被领着欢快的舞蹈)
  • 感谢@GTPE 现在提供该文档。

标签: python python-2.7 numpy pandas comments


【解决方案1】:

我会尝试解释我的代码。因为它使用了一些技巧。

  • 我将其命名为 df 为 pandas DataFrame 提供简写名称
  • 我称它为 dfg 表示将我的 df 分组。
  • 让我建立表达式dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [count_ones, len]})

    • 代码dfg = df[['bin','col7','col11']] 表示从我的DataFrame df 中获取名为“bin”、“col7”和“col11”的列。
    • 现在我有了我感兴趣的 3 列,我想按“bin”列中的值进行分组。这是由dfg = df[['bin','col7','col11']].groupby('bin') 完成的。我现在有数据组,即 bin #1 中的所有记录、bin #2 中的所有记录等。
    • 我现在想对每个 bin 组中的记录应用一些聚合函数(聚合函数类似于 sum、mean 或 count)。
    • 现在我想对每个 bin 中的记录应用三个聚合函数:“col11”的平均值、每个 bin 中的记录数以及每个 bin 中“col7”等于的记录数一。平均值很容易; numpy 已经有一个计算平均值的函数。如果我只是在做'col11'的意思,我会写:dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean]})。记录的数量也很容易; python 的len 函数(它不是真正的函数,而是列表等的属性)将为我们提供列表中的项目数。所以我现在有dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [len]})。现在我想不出一个现有的函数来计算 numpy 数组中的个数(它必须在 numpy 数组上工作)。我可以定义我自己的在 numpy 数组上工作的函数,因此我的函数 count_ones
    • 现在我将解构count_ones 函数。传递给函数的变量 x 始终是一维 numpy 数组。在我们的特定情况下,它将是 bin#1 中的所有“col7”值,bin#2 中的所有“col7”值等。代码x==1 将创建一个布尔(真/假)数组与 x 大小相同。如果 x 中的对应值等于 1,则布尔数组中的条目将为 True,否则为 false。因为如果我对布尔数组的值求和,python 将 True 视为 1,我将得到 ==1 的值的计数。现在我有了count_ones 函数,我将它应用到'col7' by:dfg = df[['bin','col7','col11']].groupby('bin').agg({'col11': [np.mean], 'col7': [count_ones, len]})

    • 可以看到.agg的语法是.agg({'column_name_to_apply_to': [list_of_function names_to_apply]}

    • 使用布尔数组,您可以进行各种奇怪的条件组合 (x==6) | (x==3) 将是“x 等于 6 或 x 等于 3”。 'and' 运算符是 &。始终在每个条件周围加上()

  • 现在到dfg.index = labels[dfg.index]。在dfg中,因为我按'bin'分组,所以每行分组数据(即我的dfg.index)的索引(或行标签)将是我的bin编号:1,2,3,labels[dfg.index]正在使用numpy 数组的精美索引。标签[0] 会给我第一个标签,标签[3] 会给我第四个标签。使用普通的 python 列表,您可以使用切片来执行标签 [0:3],这会给我标签 0,1 和 2。使用 numpy 数组,我们可以更进一步,只需使用值列表或另一个数组进行索引,以便标签[np.array([0,2,4]) 会给我标签 0,2,4。通过使用labels[dfg.index],我请求与 bin# 对应的标签。基本上我将我的垃圾箱号更改为垃圾箱标签。我本可以对原始数据执行此操作,但那将是数千行;通过在分组之后进行操作,我将这样做到 21 行左右。请注意,我不能只做dfg.index = labels,因为我的一些垃圾箱可能是空的,因此不会出现在按数据分组中。

  • 现在是dfg.ix['x',('col11', 'mean')]='N/A' 部分。记得早在我做df.ix[df.col11 == 'x', 'col11']=-0.08 时,我所有的无效数据都被视为一个数字,并将被放入第一个 bin 中。在应用 group by 和聚合函数后,我的第一个 bin 中“col11”值的平均值将为 -0.08(因为所有这些值都是 -0.08)。现在我知道这不正确,所有 -0.08 的值实际上都表明原始值 wsa x。你不能做 x 的平均值。所以我手动将其设置为 N/A。 IE。 dfg.ix['x',('col11', 'mean')]='N/A' 表示在 dfg 中索引(或行)为“x”且列为“col11 mean”)将值设置为“N/A”。 ('col11', 'mean') 我相信 pandas 是如何提出聚合列名称的,即当我使用 .agg({'col11': [np.mean]}) 时,要引用我需要的结果聚合列 ('column_name', 'aggregate_function_name')

这一切的动机是:将所有数据转换为数字,以便我可以使用 Pandas 的强大功能,然后在处理后手动更改任何我知道是垃圾的值。如果您需要更多解释,请告诉我。

【讨论】:

猜你喜欢
  • 2021-05-16
  • 2020-06-17
  • 2013-04-30
  • 1970-01-01
  • 1970-01-01
  • 2014-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多