代码之家  ›  专栏  ›  技术社区  ›  ShanZhengYang

如何使用数据帧计算列表字典?

  •  1
  • ShanZhengYang  · 技术社区  · 6 年前

    我在Python3.x中有两个字符串,它们被定义为相同的长度:

    string1 = 'WGWFTSJKPGP'
    string2 = 'DORKSRQKYJG'
    

    我还得到了一个整数,用来表示 string2 . 在这种情况下, start_pos = 51

    目标是基于索引创建一个字典。所以, string1 开始于 0 , 字符串2 开始于 51

    {0: 51, 1: 52, 2: 53, 3: 54, 4: 55, 5: 56, 6: 57, 7: 58, 8: 59, 9: 60, 10: 61}
    

    可通过以下方式构造(给出上述变量):

    convert_dict = {i: i + start_pos for i, _ in enumerate(string1)}
    

    import pandas as pd
    
    dict1 = {'column1':['MXRBMVQDHF', 'LJNVTJOY', 'LJNVTJOY', 'LJNVTJOY', 'WHLAOECVQR'], 'column2':['DPBVNJYANX', 'UWRAWDOB', 'PEKUYUQR', 'WPMLFVFZ', 'CUTQVWHRIJ'], 'start':[79, 31, 52, 84, 18]}
    
    df = pd.DataFrame(dict1)
    print(df)
    #       column1     column2  start
    # 0  MXRBMVQDHF  DPBVNJYANX     79
    # 1    LJNVTJOY    UWRAWDOB     31
    # 2    LJNVTJOY    PEKUYUQR     52
    # 3    LJNVTJOY    WPMLFVFZ     84
    # 4  WHLAOECVQR  CUTQVWHRIJ     18
    

    列中有多个相同字符串的条目 column1 . 在这种情况下,字典中的坐标 LJNVTJOY 应该是:

    {0: [31, 52, 84], 1: [32, 53, 85], 2: [33, 54, 86], 3: [34, 55, 87], 
         4: [35, 56, 88], 5: [36, 57, 89], 6: [37, 58, 90], 7: [38, 59, 91]}
    

    我想用这个数据框来计算类似的坐标字典。这样的 .groupby('column1') 语句似乎应该使用 .apply()

    以下是正确的输出(保持数据帧结构)。这里是数据帧 df2 有一列 'new_column' 使其看起来如下所示:

    df2.new_column
    0    {0: 79, 1: 80, 2: 81, 3: 82, 4: 83, 5: 84, 6: ...
    1    {0: [31, 52, 84], 1: [32, 53, 85], 2: [33, 54, 86], 3: [34, 55, 87], 4: [35, 56, 88], 5: [36, 57, 89], 6: [37, 58, 90], 7: [38, 59, 91]}
    2    {0: 52, 1: 53, 2: 54, 3: 55, 4: 56, 5: 57, 6: ...
    Name: new, dtype: object
    
    3 回复  |  直到 6 年前
        1
  •  1
  •   Vivek Kalyanarangan    6 年前

    使用-

    def dict_op(x):
        string1 = x['column1']
        string2 = x['column2']
        start_pos = x['start']
        x['val'] = {i: i + start_pos for i, _ in enumerate(string1)}
        return x
    
    def zip_dict(x):
        b=pd.DataFrame(x)
        return {i:b.loc[:,i].tolist() for i in b.columns }
    
    op = df.apply(dict_op, axis=1).groupby('column1')['val'].apply(list).apply(zip_dict)
    print(op)
    

    输出

    column1
    LJNVTJOY      {0: [31, 52, 84], 1: [32, 53, 85], 2: [33, 54,...
    MXRBMVQDHF    {0: [79], 1: [80], 2: [81], 3: [82], 4: [83], ...
    WHLAOECVQR    {0: [18], 1: [19], 2: [20], 3: [21], 4: [22], ...
    Name: val, dtype: object
    

    解释

    这个 dict_op .apply(list) 将dicts拉到一起形成dicts列表。

    这个 zip_dict() 然后创建输出 dict 临时输出。

    最后一个我没有包含的部分是,如果列表的长度是1,那么您可以只包含第一个元素,从中获取输出 {0: [79], 1: [80], 2: [81], 3: [82], 4: [83], ... {0: 79, 1: 80, 2: 81, 3: 82, 4: 83, ...

        2
  •  1
  •   Ernest S Kirubakaran    6 年前

    首先应用groupby函数将“start”列聚合为一个列表

    df2 = df.groupby("column1")["start"].apply(list).reset_index()
    

    现在,您可以编写一个函数来创建新的dictionary列

    def create_dict(row):
        new_dict = {}
        for i, j in enumerate(row["column1"]):
            if len(row["start"]) == 1:
                new_dict[i] = row["start"][0]+i
            else:
                for k in row["start"]:
                    if i in new_dict:
                        new_dict[i].append(k + i)
                    else:
                        new_dict[i] = [k + i]
        return new_dict
    

    最后,将此函数应用于df2的所有行

    df2["new_column"] = df2.apply(create_dict, axis = 1)
    
        3
  •  1
  •   cpander    6 年前

    这里有一个稍微不同的方法,使用 lambda 还有两个 zips .

    df2 = df.groupby('column1')['start'].agg([('s', list)]).reset_index()
    df2['l'] = df.column1.str.len()
    
    df2.apply(lambda x: dict(zip(range(x['l'] + 1), zip(*[range(s, s + x['l'] + 1) for s in x['s']]))), axis = 1)
    

    这里可以看到它的截断输出(注意它返回元组而不是列表):

    0    {0: (31, 52, 84), 1: (32, 53, 85), 2: (33, 54,...
    1    {0: (79,), 1: (80,), 2: (81,), 3: (82,), 4: (8...
    2    {0: (18,), 1: (19,), 2: (20,), 3: (21,), 4: (2...
    

    首先,要缩短比赛时间 apply column1 值和相关的起始位置。另外,添加长度为的列 第1栏

    第1栏 字母索引( 0 len(column1) ,用作键,并且相同的范围偏移 start

    第二种情况有点冒险 zip 因为 [range(s, s + x['l'] + 1) for s in x['s']] 返回如下内容(对于'LJNVTJOY'):

    [[31, 32, 33, 34, 35, 36, 37, 38, 39],
     [52, 53, 54, 55, 56, 57, 58, 59, 60],
     [84, 85, 86, 87, 88, 89, 90, 91, 92]]
    

    当我们真的要将垂直对齐的元素分组时,所以我们使用'splat'或' unpacking '运算符将这些列表输入 拉链 . 一旦我们组合了这些列表,我们就有了一个键列表和一个值列表(元组),它们可以是 zipped 变成一个 dict .