根据不同的值创建新列并计算它们

Create new columns based on distinct values and count them

如果标题不够清楚,请见谅。让我解释一下我想要实现的目标。

我有这个 Data-Frame,我们称它为 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

我想根据现有 Data-Frame 中的值创建一个新的 Data-Frame。首先,我想在 df 中找到不同 id 的总和。前任。 id A 有 3 个条目,B 有 2 个条目,等等。然后从中创建一个新的数据框。

对于我们的新 Data-Frame,我们称它为 df_new

id | count 
 A    3
 B    2
 C    2
 D    4

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

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

代码很长,难以阅读。它还受到警告 "A value is trying to be set on a copy of a slice from a DataFrame" 的影响。我想了解更多有关如何有效编写此内容的信息。

谢谢

第一部分可以使用 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