根据不同的值创建新列并对其进行计数

时间:2017-08-22 02:43:19

标签: python pandas dataframe crosstab

如果标题不够清晰,请注意。让我解释一下我想要实现的目标。

我有这个数据框,我们称之为df。

id | Area
A    one
A    two
A    one
B    one
B    one
C    one
C    two
D    one
D    one
D    two
D    three

我想基于现有数据框架中的值创建一个新的数据框架。首先,我想在df中找到不同id的总和。防爆。 id A有3个条目,B有2个条目,等等。然后从中创建一个新的数据帧。

对于我们的新数据框架,我们称之为df_new

id | count 
 A    3
 B    2
 C    2
 D    4

接下来,我想基于df ['Area']中的值创建一个新列,对于此示例,df ['Area']包含3个不同的值(一,二,三)。我想计算一个id在哪个区域的次数。例如,id A已经在区域1中两次,一次在区域2中,零区域在区域3中。然后,我将这些值附加到一个名为1,2和3的新列中。

df_new:

id | count | one | two | three
 A    3       2     1      0
 B    2       2     0      0
 C    2       1     1      0
 D    4       2     1      1

我已经开发了自己的代码来生成df_new,但我相信Pandas有更好的功能来执行这种数据提取。这是我的代码。

#Read the data
df = pd.read_csv('test_data.csv', sep = ',')
df.columns = ['id', 'Area'] #Rename
# Count a total number of Area by Id
df_new = pd.DataFrame({'count' : df.groupby("id")["Area"].count()})
# Reset index
df_new = df_new.reset_index()
#For loop for counting and creating a new column for areas in df['Area']
for i in xrange(0, len(df)):
    #Get the id
    idx = df['id'][i]
    #Get the areaname
    area_name = str(df["Area"][i])
    #Retrieve the index of a particular id
    current_index = df_new.loc[df_new['id'] == idx, ].index[0]
    #If area name exists in a column
    if area_name in df_new.columns:
        #Then +1 at the Location of the idx (Index)
        df_new[area_name][current_index] += 1
    #If not exists in the columns
    elif area_name not in df_new.columns:
        #Create an empty one with zeros
        df_new[area_name] = 0
        #Then +1 at the location of the idx (Index)
        df_new[area_name][current_index] += 1

代码很长很难阅读。它还受到警告“正在尝试在DataFrame的片的副本上设置值”的警告。我想更多地了解如何有效地写这个。

谢谢

1 个答案:

答案 0 :(得分:0)

您可以使用df.groupby.count作为第一部分,pd.crosstab作为第二部分。然后,使用pd.concat加入em:

In [1246]: pd.concat([df.groupby('id').count().rename(columns={'Area' : 'count'}),\
                      pd.crosstab(df.id, df.Area)], 1)
Out[1246]: 
    count  one  three  two
id                        
A       3    2      0    1
B       2    2      0    0
C       2    1      0    1
D       4    2      1    1

这是使用df.groupby的第一部分:

df.groupby('id').count().rename(columns={'Area' : 'count'})

    count
id       
A       3
B       2
C       2
D       4 

这是pd.crosstab的第二部分:

pd.crosstab(df.id, df.Area)

Area  one  three  two
id                   
A       2      0    1
B       2      0    0
C       1      0    1
D       2      1    1

对于第二部分,您还可以使用pd.get_dummies并执行点积:

(pd.get_dummies(df.id).T).dot(pd.get_dummies(df.Area))

   one  three  two
A    2      0    1
B    2      0    0
C    1      0    1
D    2      1    1