Python3.x中有两个字符串,它们定义为相同的长度:
string1 = 'WGWFTSJKPGP'
string2 = 'DORKSRQKYJG'
我还得到一个整数,该整数表示string2
的“起始索引”。在这种情况下,start_pos = 51
。
目标是根据索引创建字典。因此,string1
从0
开始,string2
从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)}
我目前以pandas DataFrame的形式获取此数据:
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]}
我想使用此DataFrame并计算类似的坐标字典。这样的.groupby('column1')
语句似乎应该以某种方式使用.apply()
?我不确定如何填充这样的字典列表...
这是正确的输出(保留DataFrame结构)。这里的DataFrame 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
答案 0 :(得分:1)
首先应用groupby函数将“开始”列汇总为列表
df2 = df.groupby("column1")["start"].apply(list).reset_index()
现在,您可以编写一个函数来创建新的字典列
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)
答案 1 :(得分:1)
使用-
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)
将字典压缩在一起以形成字典列表。
然后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)
这里使用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
值和关联的起始位置的DataFrame。另外,添加一个长度为column1
的列(假定等长断言成立)。
此后,只需合并column1
个字母索引(0
到len(column1)
的范围(用作键)和相同范围(由{{1 }}值。
第二个start
会带来一些麻烦,因为zip
返回的内容类似于(对于'LJNVTJOY'):
[range(s, s + x['l'] + 1) for s in x['s']]
当我们真的想对垂直对齐的元素进行分组时,可以使用'splat'或'unpacking'运算符将这些列表输入[[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]]
中。合并这些列表之后,我们将获得一个键列表和一个(元组)值列表,它们可以zip
变成zipped
。