了解这个Pandas脚本

时间:2013-11-02 23:15:33

标签: python python-2.7 numpy pandas comments

我收到此代码可将数据分组为直方图类型数据。我一直试图理解这个pandas脚本中的代码,以便编辑,操作和复制它。我对我理解的部分有评论。

代码

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')

如果有人能够评论这个剧本,我将非常感激。也可以随意纠正或添加我的评论(这些是我假设到目前为止他们可能不正确)。我希望这不是SOF的主题。我很乐意为任何可以帮助我的用户提供50点奖励。

1 个答案:

答案 0 :(得分:8)

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

  • 我已将其称为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']]正在说出名为&#39; bin&#39;的列。 &#39; COL7&#39;和&#39; col11&#39;来自我的DataFrame df
    • 现在我有了我感兴趣的3列,我想根据&#39; bin&#39;中的值进行分组。柱。这是由dfg = df[['bin','col7','col11']].groupby('bin')完成的。我现在有数据组,即bin#1中的所有记录,bin#2中的所有记录等等。
    • 我现在想将一些聚合函数应用于每个bin组中的记录(聚合函数类似于sum,mean或count)。
    • 现在我想将三个聚合函数应用于每个箱子中的记录:&#39; col11&#39;的平均值,每个箱子中的记录数量,以及每个箱子中的记录数量&#39; COL7&#39;等于一。意思很简单; numpy已经具有计算均值的函数。如果我只是做着#col;&#39;我会写: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函数。传递给函数的varibale x总是一个1d numpy数组。在我们的具体情况下,它将是所有&#39; col7&#39; bin#1中的值,所有&#39; col7&#39;落在bin#2等中的值。代码x==1将创建一个与x相同大小的布尔(TRUE / FALSE)数组。如果x中的相应值等于1,则布尔数组中的条目将为True,否则为false。因为如果我将我的布尔数组的值相加,python将True视为1,我将得到== 1的值的计数。现在我已经拥有了count_ones功能,我将其应用于&#39; col7&#39;作者: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; x等于6或x等于3&#39;。 &#39;和&#39;运营商是&amp ;.始终将()置于每个条件

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

  • 现在是dfg.ix['x',('col11', 'mean')]='N/A'部分。请记住当我执行df.ix[df.col11 == 'x', 'col11']=-0.08时,我的所有无效数据都被视为一个数字并将被放入第一个bin中。在应用分组和汇总功能后,&#39; col11&#39;的平均值我的第一个bin中的值将是-0.08(因为所有这些值都是-0.08)。现在我知道这不正确,-0.08的所有值实际上表示原始值为wsa x。你不能做x的意思。所以我手动把它放到N / A.即。 dfg.ix['x',('col11', 'mean')]='N/A'表示在dfg中,索引(或行)是&#39; x&#39;和列是&#39; col11表示&#39;)将值设置为&#39; N / A&#39;。 ('col11', 'mean')我相信大熊猫是如何提出聚合列名称的,即当我.agg({'col11': [np.mean]})时,引用我需要('column_name', 'aggregate_function_name')

  • 的结果聚合列

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