关于python:使用来自同一行但不同列的值填充字典

Fill dictionary with value from the same row, but different column

最近我一直在尝试映射一些值,所以我正试图创建一个字典来实现这一点。奇怪的是,我的数据框架有一个由列表组成的列,而数据框架总是对列表有点笨拙。数据帧具有以下结构:

1
2
3
4
    rules          procedure
['10','11','12']       1
['13','14']            2
['20','21','22','24']  3

所以我想创建一个字典,它将"10"映射到1,"14"映射到2,依此类推。我尝试了以下方法:

1
2
3
4
dicc=dict()
for j in df['rules']:
    for i,k in zip(j,df.procedure):
        dicc[i]=k

但这不可能。可能与索引有关。我错过了什么?

编辑:我正在创建一个字典,它将值"10"、"11"、"12"映射到1;"13"、"14"映射到2;"20"、"21"、"22"、"24"映射到3,所以如果我键入dicc['10'],我会得到1,如果我键入dicc['22'],我会得到3。显然,实际的数据帧要大得多,我不能手动操作。


你可以这样做:

1
2
3
4
5
6
7
8
9
10
import pandas as pd

data = [[['10', '11', '12'], 1],
        [['13', '14'], 2],
        [['20', '21', '22', '24'], 3]]

df = pd.DataFrame(data=data, columns=['rules', 'procedure'])

d = {r : p for rs, p in df[['rules', 'procedure']].values for r in rs}
print(d)

产量

1
{'20': 3, '10': 1, '11': 1, '24': 3, '14': 2, '22': 3, '13': 2, '12': 1, '21': 3}

笔记:

  • 代码{r : p for rs, p in df[['rules', 'procedure']].values for r
    in rs}
    是一个字典理解,字典对应的名单。
  • df[['rules', 'procedure']].values相当于它输出一对列表,因此rs变量是一个列表,p是一个整数。
  • 最后,使用第二个for循环迭代rs的值

更新

如@pirsquared的建议,您可以使用zip:

1
d = {r : p for rs, p in zip(df.rules, df.procedure) for r in rs}


来自cytoolz的帮助

1
2
3
4
5
6
7
8
9
10
11
12
13
from cytoolz.dicttoolz import merge

merge(*map(dict.fromkeys, df.rules, df.procedure))

{'10': 1,
 '11': 1,
 '12': 1,
 '13': 2,
 '14': 2,
 '20': 3,
 '21': 3,
 '22': 3,
 '24': 3}

注释

我更新了我的帖子来模仿@jpp如何将多个iterables传递给map。@JPP的回答很好。虽然我主张对所有有用的答案都进行投票,但我希望我能再次对他们的答案进行投票(—:


使用collections.ChainMap

1
2
3
4
5
6
7
8
from collections import ChainMap

res = dict(ChainMap(*map(dict.fromkeys, df['rules'], df['procedure'])))

print(res)

{'10': 1, '11': 1, '12': 1, '13': 2, '14': 2,
 '20': 3, '21': 3, '22': 3, '24': 3}

对于许多用途,不需要最终的dict转换:

A ChainMap class is provided for quickly linking a number of
mappings so they can be treated as a single unit. It is often much
faster than creating a new dictionary and running multiple update()
calls.

另请参见collections.chainmap的用途是什么?


你可以勾选"展平列表"

1
2
3
4
5
6
7
8
9
10
11
dict(zip(sum(df.rules.tolist(),[]),df.procedure.repeat(df.rules.str.len())))
Out[60]:
{'10': 1,
 '11': 1,
 '12': 1,
 '13': 2,
 '14': 2,
 '20': 3,
 '21': 3,
 '22': 3,
 '24': 3}

使用itertools.chainDataFrame.itertuples时:

1
2
3
4
5
dict(
    chain.from_iterable(
        ((rule, row.procedure) for rule in row.rules) for row in df.itertuples()
    )
)