【问题标题】:How to modify values in a list of lists based on a sub-value如何根据子值修改列表列表中的值
【发布时间】:2018-05-24 21:48:17
【问题描述】:

我在尝试解决这个问题时遇到了很大的挑战。我有这个列表列表:

[['060710080013011', 9],
 ['060710080013011', 9],
 ['060710080013011', 9],
 ['060710080013011', 9],
 ['060710080013011', 9],
 ['060710080013011', 9],
 ['060710080013011', 9],
 ['060710080013011', 9],
 ['060710080013011', 9],
 ['060710080013033', 8],
 ['060710080013033', 8],
 ['060710080013033', 8],
 ['060710080013033', 8],
 ['060710080013033', 8],
 ['060710080013033', 8],
 ['060710080013033', 8],
 ['060710080013033', 8],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15],
 ['060710080021000', 15]]

第一个值是一个 ID,第二个值是这个 ID 在列表列表中出现的次数。问题如下:

当第二个值大于 7 时,我需要更改每个元组中每隔一个项目中的值,这里是所需的输出:

[['060710080013011', 7],
 ['060710080013011', 7],
 ['060710080013011', 7],
 ['060710080013011', 7],
 ['060710080013011', 7],
 ['060710080013011', 7],
 ['060710080013011', 7],
 ['060710080013011_2', 2],
 ['060710080013011_2', 2],
 ['060710080013033', 7],
 ['060710080013033', 7],
 ['060710080013033', 7],
 ['060710080013033', 7],
 ['060710080013033', 7],
 ['060710080013033', 7],
 ['060710080013033', 7],
 ['060710080013033_2', 1],
 ['060710080021000', 7],
 ['060710080021000', 7],
 ['060710080021000', 7],
 ['060710080021000', 7],
 ['060710080021000', 7],
 ['060710080021000', 7],
 ['060710080021000', 7],
 ['060710080021000_2', 7],
 ['060710080021000_2', 7],
 ['060710080021000_2', 7],
 ['060710080021000_2', 7],
 ['060710080021000_2', 7],
 ['060710080021000_2', 7],
 ['060710080021000_2', 7],
 ['060710080021000_3', 1]]

如果您在上面看到我想要的输出,我需要更改每个数字大于 7 的子列表的第二项。

如果您需要澄清问我,我的母语不是英语,但我可以做到最好。

【问题讨论】:

  • 我对您尝试对元组进行的更改感到有些困惑。如果我理解正确,每个元组中的第二个值是 ID 的“计数”,如果超过 7,这就是您要更改的值,您要将其更改为什么?在您的结果中,元组中有 3 个值而不是 2 个,您是否添加了这个以及更改第二项的值?
  • 你能解释一下你想要的输出吗?举一个实际输入的例子,以及期望的输出应该是什么。这将有助于澄清问题。
  • 如果我是正确的。 [123456789, 9] 你想改成[123456789, 7], [123456789_2, 2] 对吗?
  • 感谢您抽出时间@JamesLingham。基本上,如果您输入值,则 LIST 中的前 9 个子列表具有相同的 ID,并且作为第二个子值,所有这些都有 9。所以基本上我需要将 7 的 9 更改为前 7 个值和2 为最后 2。这有意义吗。请随时询问。
  • 那么为最后 2 次出现创建一个新 ID?元组中的第三个值来自哪里? 155 等,它似乎也可以延续到新的 ID 集,但不会出现在您的第一个列表中。

标签: python python-3.x list


【解决方案1】:
lista2 = [['100',9]]
for l in lista2:
    v = l[1] - 7
    c = 2
    while v > 0:
        l[1] = 7
        lista2.append([l[0]+"_"+str(c),min(v,7)])
        v -= 7
        c += 1

print(lista2)

应该按您的要求工作,主要是代码中的一些语法错误和错误命名的变量,如果这不起作用,请告诉我。

【讨论】:

  • 非常感谢@James。再次为混乱感到抱歉。我需要的是 9 个子列表的列表: lista2 = [['100',9].........[100;9] 得到另一个 9 个子列表的列表,如下所示: [[100,7] ,[100,7]....[100_2,2],[100_2,2)。这是因为 9-7 = 2 ,所以残差应该是第二个值。
  • 再次感谢您帮助我。我会试试你的代码!它似乎正在工作。
【解决方案2】:

一个简单的解决方案是使用 groupby 和一个简单的 Counter,这是一个可行的解决方案:

In [1]: from itertools import groupby

In [2]: from collections import Counter

In [3]: whatever = [['060710080013011', 9],  ['060710080013011', 9],  ['060710080013011', 9],  ['060710080013011', 9],  ['06071008001
   ...: 3011', 9],  ['060710080013011', 9],  ['060710080013011', 9],  ['060710080013011', 9],  ['060710080013011', 9],  ['06071008001
   ...: 3033', 8],  ['060710080013033', 8],  ['060710080013033', 8],  ['060710080013033', 8],  ['060710080013033', 8],  ['06071008001
   ...: 3033', 8],  ['060710080013033', 8],  ['060710080013033', 8],  ['060710080021000', 15],  ['060710080021000', 15],  ['060710080
   ...: 021000', 15],  ['060710080021000', 15],  ['060710080021000', 15],  ['060710080021000', 15],  ['060710080021000', 15],  ['0607
   ...: 10080021000', 15],  ['060710080021000', 15],  ['060710080021000', 15],  ['060710080021000', 15],  ['060710080021000', 15],  [
   ...: '060710080021000', 15],  ['060710080021000', 15],  ['060710080021000', 15]]

In [7]: counter = []
    ...: # we use groupby to group the inner list by key, i.e. the first label
    ...: for key, grouped in groupby(whatever, lambda x: x[0]):
    ...:     # here, we decide if we need to append the label if the item counts great than multiple of 7
    ...:     for idx, item in enumerate(grouped):
    ...:         # to get the LABEL_INDEX as new keyed
                 keyed = key if int(idx / 7) == 0 else "{}_{}".format(key, int(idx / 7) + 1)
    ...:         counter.append(keyed)
    ...: # simply use a counter to re-count the new label items
    ...: counted = Counter(counter)
    ...: answer = []
    ...: for keyed in sorted(counted):
    ...:     for _ in range(counted[keyed]):
    ...:         answer.append([keyed, counted[keyed]])
    ...:
    ...: print(answer)
    ...:
    ...:
    ...:
    ...:

[['060710080013011', 7], ['060710080013011', 7], ['060710080013011', 7], ['060710080013011', 7], ['060710080013011', 7], ['060710080013011', 7], ['060710080013011', 7], ['060710080013011_2', 2], ['060710080013011_2', 2], ['060710080013033', 7], ['060710080013033', 7], ['060710080013033', 7], ['060710080013033', 7], ['060710080013033', 7], ['060710080013033', 7], ['060710080013033', 7], ['060710080013033_2', 1], ['060710080021000', 7], ['060710080021000', 7], ['060710080021000', 7], ['060710080021000', 7], ['060710080021000', 7], ['060710080021000', 7], ['060710080021000', 7], ['060710080021000_2', 7], ['060710080021000_2', 7], ['060710080021000_2', 7], ['060710080021000_2', 7], ['060710080021000_2', 7], ['060710080021000_2', 7], ['060710080021000_2', 7], ['060710080021000_3', 1]]

【讨论】:

  • 你太棒了兄弟! ,感谢您的时间和帮助。我会检查这个!
【解决方案3】:
# arr is the input( list of list)
output = []
n = len(arr)
i=0
while i<n:
    ID, f = arr[i]
    mul = 1
    while mul*7 < f:
        if mul!=1:
            newID = ID + '_' + str(mul)
        else:
            newID = ID
        temp = [[newID,7] for j in range(7)]
        mul += 1
        output += temp

    rem = f - ((mul-1)*7)
    newID = ID +  '_' + str(mul)
    temp = [[newID, rem] for j in range(rem)]
    output += temp

    i += f

print(output)

上面的代码给出了预期的输出。

【讨论】:

  • 嘘!感谢您的时间和帮助!我会试试这个代码!
【解决方案4】:

我的解决方案如下所示:

import pandas as pd
df = pd.DataFrame(lst)
df.columns = ['ID', 'counter']

df.counter = df.groupby('ID').cumcount() // 7

df.loc[df.counter>0, 'ID'] += '_' + (df.counter + 1)[df.counter>0].astype(str)
df.counter = df.applymap(lambda id: (df.ID==id).sum())['ID']

就是这样 - 完成了。

下面我会解释每一步:

要准备好在 pandas 中处理的数据,请加载库并将数据放入数据框:

import pandas as pd
df = pd.DataFrame(lst)
df.columns = ['ID', 'counter']

最初将计数器设置为数据集中 ID 的累积计数器的模 7,可用于索引大小为 7 的子组:

df['counter'] = df.groupby('ID').cumcount() // 7

现在您的数据集如下所示:

                 ID  counter
0   060710080013011        0
1   060710080013011        0
2   060710080013011        0
3   060710080013011        0
4   060710080013011        0
5   060710080013011        0
6   060710080013011        0
7   060710080013011        1
8   060710080013011        1
9   060710080013033        0
10  060710080013033        0
11  060710080013033        0
12  060710080013033        0
13  060710080013033        0
14  060710080013033        0
15  060710080013033        0
16  060710080013033        1
17  060710080021000        0
18  060710080021000        0
19  060710080021000        0
20  060710080021000        0
21  060710080021000        0
22  060710080021000        0
23  060710080021000        0
24  060710080021000        1
25  060710080021000        1
26  060710080021000        1
27  060710080021000        1
28  060710080021000        1
29  060710080021000        1
30  060710080021000        1
31  060710080021000        2 

现在更改 ID,即仅当 counter&gt;0 将“counter+1”作为带有前下划线的字符串附加到现有 ID:

df.loc[df.counter>0, 'ID'] += '_' + (df.counter + 1)[df.counter>0].astype(str)

要将计数器更改回所需的 ID 总和,请对每个元素应用 lambda 函数,该函数返回该元素数据集中所有出现次数的总和:

df.counter = df.applymap(lambda id: (df.ID==id).sum())['ID']

那么数据集是这样的:

                   ID  counter
0     060710080013011        7      
1     060710080013011        7      
2     060710080013011        7      
3     060710080013011        7      
4     060710080013011        7      
5     060710080013011        7      
6     060710080013011        7      
7   060710080013011_2        2      
8   060710080013011_2        2      
9     060710080013033        7      
10    060710080013033        7      
11    060710080013033        7      
12    060710080013033        7      
13    060710080013033        7      
14    060710080013033        7      
15    060710080013033        7      
16  060710080013033_2        1      
17    060710080021000        7      
18    060710080021000        7      
19    060710080021000        7      
20    060710080021000        7      
21    060710080021000        7      
22    060710080021000        7      
23    060710080021000        7      
24  060710080021000_2        7      
25  060710080021000_2        7      
26  060710080021000_2        7      
27  060710080021000_2        7      
28  060710080021000_2        7      
29  060710080021000_2        7      
30  060710080021000_2        7      
31  060710080021000_3        1      

【讨论】:

  • 谢谢!! , 这难以置信。我会在 Jupiter notebook 上试试这个。
  • 如果它适合您,我很高兴 - 我很高兴改进它! :-) 但是 - 我几乎看不出它真的有用......不要误会我的意思,但是:你确定你有一个任务,这是最好的解决方案吗?
  • 大声笑——误会了!我不想拒绝你的接受,我很高兴! :-) 我只是想知道,这个算法的用例是什么,因为我不知道!
  • 所以基本上我将此代码用于称为 CASPER 方法的东西。我是一名 GIS 分析师,我需要这段代码在 CASPER 的外推过程中完成更大的 os 指令集。现在我将为我的 python 桌面工具选择@James 的选项,但您的解决方案非常适合我使用 jupiter notebooks 的工具的在线版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-04
  • 2019-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多