如何使用组的不同组合,同时试图获得最多的浏览量

2024-05-15 15:09:37 发布

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

我试图获得最高的评价使用多栏groupby,如果没有组合,特别groupby,它抛出了一个错误。如何进行多重组合?你知道吗

数据:

maritalstatus   gender age_range occ    rating
ma                 M    young   student  PG
ma                 F    adult   teacher  R
sin                M    young   student  PG
sin                M    adult   teacher  R
ma                 M    young   student  PG
sin                F    adult   teacher  R

代码:

def get_top( maritalstatus, gender,age_range, occ):        
    m = df.groupby(['maritalstatus',' gender', 'age_range', 'occ'])
    ['rating'].apply(lambda x: x.value_counts().index[0 ])      
    mpaa = m[maritalstatus][gender][age_range][occ]    
    return mpaa

输入:

get_top('ma', 'M', 'young','teacher)

输出: 给我一个错误,因为没有这样的组合。你知道吗

在这里,如果没有这样的组合,我的功能应该限制在,已婚,男性和年轻人,而不是教师,因为没有这样的组合。你知道吗


Tags: age错误rangesingenderstudentpggroupby
3条回答

可以使用^{}进行动态输入(值的顺序不能更改),使用^{}进行过滤:

def get_top(*args):     
    c = ['maritalstatus', 'gender', 'age_range', 'occ']
    m = (df.groupby(c)['rating'].apply(lambda x: x.value_counts().index[0])
           .reset_index())
    args = list(args)
    while True:
        d = dict(zip(c, args))
        #https://stackoverflow.com/a/48371587/2901002
        q = ' & '.join((('({} ==  "{}")').format(i, j)) for i, j in d.items())
        m1 = m.query(q)['rating']  
        if m1.empty and len(args) > 1:
            args.pop()
        else:
            return m1

print(get_top('ma', 'M', 'young','teacher'))
1    PG
Name: rating, dtype: object

这是一个非熊猫解决方案。Counter.most_common()按最常见的降序计数对结果进行排序。你知道吗

from collections import Counter

def get_top(maritalstatus=None, gender=None, age_range=None, occ=None):

    cols = ['maritalstatus', 'gender', 'age_range', 'occ']
    values = [maritalstatus, gender, age_range, occ]

    c = Counter(df.query(' & '.join((('({0} ==  "{1}")').format(i, j)) \
                for i, j in zip(cols, values) if j))['rating'])

    return c.most_common()

get_top(maritalstatus='ma', gender='M', age_range='young')  # [('PG', 2)]

^{}绝对是处理详细表格数据的goto库。对于那些寻求非pandas选项的人,您可以构建自己的映射还原函数。我使用这些术语的含义如下:

  • 映射:重新组织按所需查询分组的数据
  • 归约函数:一种聚合函数,用于将多个值归并成一个值

pandas类似的groupby/聚合概念。你知道吗

给定的

用单个分隔符替换多个空格的已清理数据,例如","。你知道吗

%%file "test.txt"
status,gender,age_range,occ,rating
ma,M,young,student,PG
ma,F,adult,teacher,R
sin,M,young,student,PG
sin,M,adult,teacher,R
ma,M,young,student,PG
sin,F,adult,teacher,R

代码

import csv
import collections as ct

步骤1:读取数据

def read_file(fname):
    with open(fname, "r") as f:
        reader = csv.DictReader(f)
        for line in reader:
            yield line


iterable = [line for line in read_file("test.txt")]
iterable

输出

[OrderedDict([('status', 'ma'),
              ('gender', 'M'),
              ('age_range', 'young'),
              ('occ', 'student'),
              ('rating', 'PG')]),
 OrderedDict([('status', 'ma'),
              ('gender', 'F'),
              ('age_range', 'adult'),
              ...]
 ...
] 

第2步:重新映射数据

def mapping(data, column):
    """Return a dict of regrouped data."""
    dd = ct.defaultdict(list)
    for d in data:
        key = d[column]
        value = {k: v for k, v in d.items() if k != column}
        dd[key].append(value)
    return dict(dd)


mapping(iterable, "gender")

输出

{'M': [
   {'age_range': 'young', 'occ': 'student', 'rating': 'PG', ...},
   ...]
 'F': [
   {'status': 'ma', 'age_range': 'adult', ...},
   ...]
} 

第3步:减少数据

def reduction(data):
    """Return a reduced mapping of Counters."""
    final = {}
    for key, val in data.items():
        agg = ct.defaultdict(ct.Counter)
        for d in val:
            for k, v in d.items():
                agg[k][v] += 1
        final[key] = dict(agg)
    return final

reduction(mapping(iterable, "gender"))

输出

{'F': {
   'age_range': Counter({'adult': 2}),
   'occ': Counter({'teacher': 2}),
   'rating': Counter({'R': 2}),
   'status': Counter({'ma': 1, 'sin': 1})},
 'M': {
   'age_range': Counter({'adult': 1, 'young': 3}),
   'occ': Counter({'student': 3, 'teacher': 1}),
   'rating': Counter({'PG': 3, 'R': 1}),
   'status': Counter({'ma': 2, 'sin': 2})}
 }

演示

有了这些工具,您可以构建数据管道并查询数据,将一个函数的结果输入到另一个函数中:

# Find the top age range amoung males
pipeline = reduction(mapping(iterable, "gender"))
pipeline["M"]["age_range"].most_common(1)
# [('young', 3)]

# Find the top ratings among teachers
pipeline = reduction(mapping(iterable, "occ"))
pipeline["teacher"]["rating"].most_common()
# [('R', 3)]

# Find the number of married people
pipeline = reduction(mapping(iterable, "gender"))
sum(v["status"]["ma"] for k, v in pipeline.items())
# 3

总的来说,您可以根据如何定义缩减函数来定制输出。你知道吗

注意,这个通用过程的代码比former example更冗长,尽管它对许多数据列有强大的应用。pandas简洁地封装了这些概念。虽然学习曲线最初可能更陡峭,但它可以大大加快数据分析。你知道吗


细节

  1. 读取数据-我们使用^{}解析清理文件的每一行,它将头名称作为字典的键来维护。这种结构便于按名称访问列。你知道吗
  2. 重新映射数据-我们将数据分组为字典。
    • 键是选定/查询列中的项,例如"M""F"。你知道吗
    • 每个值都是一个字典列表。每个字典表示一行所有剩余的列数据(不包括键)。你知道吗
  3. Reduce data—我们通过将所有列出的字典的相关条目制成表格,来聚合重新映射的数据的值。将^{}^{}组合在一起可以构建一个优秀的简化数据结构,其中defaultdict的新条目初始化Counter,而重复的条目只是记录观察结果。你知道吗

应用程序

管道是可选的。在这里,我们将构建一个处理串行请求的函数:

def serial_reduction(iterable, val_queries):
    """Return a `Counter` that is reduced after serial queries."""
    q1, *qs = val_queries 
    val_to_key = {v:k for k, v in iterable[0].items()}
    values_list = mapping(iterable, val_to_key[q1])[q1]

    counter = ct.Counter()
    # Process queries for dicts in each row and build a counter
    for q in qs:    
        try:
            for row in values_list[:]:
                if val_to_key[q] not in row:
                    continue
                else:
                    reduced_vals = {v for v in row.values() if v not in qs}
            for val in reduced_vals:
                counter[val] += 1
        except KeyError:
            raise ValueError("'{}' not found. Try a new query.".format(q))
    return counter


c = serial_reduction(iterable, "ma M young".split())
c.most_common()
# [('student', 2), ('PG', 2)]
serial_reduction(iterable, "ma M young teacher".split())
# ValueError: 'teacher' not found. Try a new query.

相关问题 更多 >