创建df或其他数组,对满足特定条件的其他df的条目进行计数

2024-06-16 17:25:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含如下条目的当前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中每个日期具有特定ease的时间。例如,如果我想计算每个标记的易用性为1的次数,它将如下所示:

       date1    date2
tag1   2        1
tag2   1        2   
tag3   0        1 

我可以想办法用循环来实现这一点,但是我的最终输出大约是700 x 800,我需要为每个“ease”做一个。我觉得必须有一个有效的方法来使用索引来实现这一点,因此我首先考虑熊猫。如前所述,我对Python非常陌生,如果有其他的方法或包我应该考虑使用,我是开放的。你知道吗


Tags: 方法标记目的类型dfdatetags数组
3条回答

这里有一个选项;使用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

我想你需要^{}^{}

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^{}^{}一起使用,并对^{}进行整形:

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

编辑:

在测试完我发布的解决方案后,需要添加函数^{}^{},因为如果过滤掉非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的第二个解决方案通常是错误的,所以我从计时中省略了它)

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

您可以考虑在DataFrame上使用pivot\u table方法,并使用自己的函数来做一些只有在您想要的条件为真时才有意义的事情。然后,如果没有0的数据,也应该填充标记和日期。比如:

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)

相关问题 更多 >