2017-04-15 55 views
2

我有一个包含这样的条目的当前DF:创建DF或其他阵列,从另一个DF会议登载项具体准则

 date  tags  ease 
0 'date1' 'tag1' 1 
1 'date1' 'tag1' 2 
2 'date1' 'tag1' 1 
3 'date1' 'tag2' 2 
4 'date1' 'tag2' 2 
5 'date2' 'tag1' 3 
6 'date2' 'tag1' 1 
7 'date2' 'tag2' 1 
8 'date2' 'tag3' 1 

我想创建一个DF(或一些其他类型的数组,如果有是一个更好的方式去做这件事 - 我对Python是绿色的并且欢迎提出建议),它计算特定标签对df中每个日期具有特定缓解的时间。例如,如果我想算的次数每个标签都有一个轻松的1会是这个样子:

 date1 date2 
tag1 2  1 
tag2 1  2 
tag3 0  1 

我可以想办法做到这一点使用一个循环,但我的最终输出将会是大约700×800,我需要为每个“缓解”做一个。我觉得必须有一个有效的方法来使用索引来做到这一点,因此我首先看熊猫。正如我所说的,如果有其他方法或软件包我应该考虑使用,我对Python很陌生,我对它开放。

+2

请发布您已经做过的任何尝试。 – blacksite

+0

我还没有尝试索引。说实话,我很乐意收到一些功能或其他软件包的建议,我应该考虑使用,我可以从那里探索。我知道SO在这里不是我可以使用的编码器的来源,我只是想知道要走什么方向,所以我可以从那里自学。如有必要,我可以编辑帖子以反映这一点。 – jk3

+1

@ jk3:不幸的是,SO也不适合提供关于图书馆或软件包的建议或建议(答案往往是基于意见的。) – DSM

回答

2

我认为你需要boolean indexingcrosstab

df1 = df[df['ease'] == 1] 
df = pd.crosstab(df1['tags'], df1['date']) 
print (df) 
date 'date1' 'date2' 
tags      
'tag1'  2  1 
'tag2'  0  1 
'tag3'  0  1 

另一种解决方案,而不是crosstab使用groupbysize和重塑unstack

df = df[df['ease'] == 1].groupby(["date", "tags"]).size().unstack(level=0, fill_value=0) 
print (df) 
date 'date1' 'date2' 
tags      
'tag1'  2  1 
'tag2'  0  1 
'tag3'  0  1 

编辑:测试解决方案

后,我发布是需要添加功能reindexsort_index,因为如果过滤非1输出值,它将删除最后的DataFrame中的行。

print (df[df['ease'] == 1].groupby(["date", "tags"]) 
          .size() 
          .unstack(level=0, fill_value=0) 
          .reindex(index=df.tags.unique(), columns=df.date.unique(), fill_value=0) 
          .sort_index() 
          .sort_index(axis=1)) 

而且也第二溶液:

df1 = df[df['ease'] == 1] 
df2 = pd.crosstab(df1['tags'], df1['date']) 
     .reindex(index=df.tags.unique(), columns=df.date.unique(), fill_value=0) 
     .sort_index() 
     .sort_index(axis=1) 

时序

(Psidom的第二溶液是错误的一般DF,所以省略它从定时)

np.random.seed(123) 
N = 10000 
dates = pd.date_range('2017-01-01', periods=100) 
tags = ['tag' + str(i) for i in range(100)] 
ease = range(10) 
df = pd.DataFrame({'date':np.random.choice(dates, N), 
        'tags': np.random.choice(tags, N), 
        'ease': np.random.choice(ease, N)}) 
df = df.reindex_axis(['date','tags','ease'], axis=1) 
#[10000 rows x 3 columns] 
#print (df) 
print (df.groupby(["date", "tags"]).agg({"ease": lambda x: (x == 1).sum()}).ease.unstack(level=0).fillna(0)) 

print (df[df['ease'] == 1].groupby(["date", "tags"]).size().unstack(level=0, fill_value=0).reindex(index=df.tags.unique(), columns=df.date.unique(), fill_value=0).sort_index().sort_index(axis=1)) 

def jez(df): 
    df1 = df[df['ease'] == 1] 
    return pd.crosstab(df1['tags'], df1['date']).reindex(index=df.tags.unique(), columns=df.date.unique(), fill_value=0).sort_index().sort_index(axis=1) 

print (jez(df)) 

#Psidom solution 
In [56]: %timeit (df.groupby(["date", "tags"]).agg({"ease": lambda x: (x == 1).sum()}).ease.unstack(level=0).fillna(0)) 
1 loop, best of 3: 1.94 s per loop 

In [57]: %timeit (df[df['ease'] == 1].groupby(["date", "tags"]).size().unstack(level=0, fill_value=0).reindex(index=df.tags.unique(), columns=df.date.unique(), fill_value=0).sort_index().sort_index(axis=1)) 
100 loops, best of 3: 5.74 ms per loop 

In [58]: %timeit (jez(df)) 
10 loops, best of 3: 54.5 ms per loop 
+0

请检查编辑的答案,我添加reindex和sort_index功能相同的输出,并添加时间。在我看来有很大的不同,因为更快的过滤首先是为了更小的df,其中通常使用'groupby'函数来缓和'agg'过滤每个组。 – jezrael

1

这里是一个选项;使用groupby.agg计算count,然后unstack结果以宽幅:

(df.groupby(["date", "tags"]) 
    .agg({"ease": lambda x: (x == 1).sum()}) 
    .ease.unstack(level=0).fillna(0)) 

enter image description here

或者,如果你喜欢用crosstab

pd.crosstab(df.tags, df.date, df.ease == 1, aggfunc="sum").fillna(0) 

# date 'date1' 'date2' 
# tags  
#'tag1' 2.0 1.0 
#'tag2' 0.0 1.0 
#'tag3' 0.0 1.0 
0

你可以看看使用pivot_table方法在DataFrame上用你自己的函数做一些事情,只有当你想要的条件是真时才算。这也应该填充没有数据的标签和日期。例如:

def calc(column): 
    total = 0 
    for e in column: 
     if e == 1: 
      total += 1 
    return total 

check_res = df.pivot_table(index='tags',columns='date', values='ease', aggfunc=calc, fill_value=0)