繁体   English   中英

对行进行迭代的熊猫数据帧由数组组成,并根据条件计算移动平均值

[英]Iterate pandas data frame for rows consists of arrays and compute a moving average based on condition

我想不出我要解决的问题。 我有一个来自此的熊猫数据框:

date,       id,     measure,    result
2016-07-11, 31, "[2, 5, 3, 3]",     1
2016-07-12, 32, "[3, 5, 3, 3]",     1
2016-07-13, 33, "[2, 1, 2, 2]",     1
2016-07-14, 34, "[2, 6, 3, 3]",     1
2016-07-15, 35, "[39, 31, 73, 34]", 0
2016-07-16, 36, "[3, 2, 3, 3]",     1
2016-07-17, 37, "[3, 8, 3, 3]",     1

Measurements列由字符串格式的数组组成。

我想从过去的3条测量记录中得到一个新的 moving-average-array列,不包括result为0的那些记录。过去的3条记录意味着对于id 34,将使用id 31、32、33的数组。

这是关于获取每个moving-average-array第一,第二,第三和第四点moving-average-array

它是不是让1个数组,第2个数组...的平均值,然后平均平均, 没有

对于前3行,由于没有足够的历史记录,我只想使用自己的度量。 因此,解决方案应如下所示:

date,       id,     measure,    result .     Solution
2016-07-11, 31, "[2, 5, 3, 3]",     1,      "[2,   5, 3,   3]"
2016-07-12, 32, "[3, 5, 3, 3]",     1,      "[3,   5, 3,   3]"
2016-07-13, 33, "[2, 1, 2, 2]",     1,      "[2,   1, 2,   2]"
2016-07-14, 34, "[2, 6, 3, 3]",     1,      "[2.3, 3.6, 2.6, 2.6]"
2016-07-15, 35, "[39, 31, 73, 34]", 0,      "[2.3, 4, 2.6, 2.6]"
2016-07-16, 36, "[3, 2, 3, 3]",     1,      "[2.3, 4, 2.6, 2.6]"
2016-07-17, 37, "[3, 8, 3, 3]",     1,      "[2.3, 3, 2.6, 2.6]"

实际数据更大。 result 0也可能彼此重复2次或更多次。 我认为这将与跟踪先前的OK result以正确获取这些平均值。 我花了时间,但我没有。

我在这里发布数据框:

 mydict = {'date': {0: '2016-07-11',
      1: '2016-07-12',
      2: '2016-07-13',
      3: '2016-07-14',
      4: '2016-07-15',
      5: '2016-07-16',
      6: '2016-07-17'},
     'id': {0: 31, 1: 32, 2: 33, 3: 34, 4: 35, 5: 36, 6: 37},
     'measure': {0: '[2, 5, 3, 3]',
      1: '[3, 5, 3, 3]',
      2: '[2, 1, 2, 2]',
      3: '[2, 6, 3, 3]',
      4: '[39, 31, 73, 34]',
      5: '[3, 2, 3, 3]',
      6: '[3, 8, 3, 3]'},
     'result': {0: 1, 1: 1, 2: 1, 3: 1, 4: 0, 5: 1, 6: 1}}

df = pd.DataFrame(mydict)

感谢您提供指导或指出操作方法。

仅使用1 for循环的解决方案:

考虑数据:

mydict = {'date': {0: '2016-07-11',
      1: '2016-07-12',
      2: '2016-07-13',
      3: '2016-07-14',
      4: '2016-07-15',
      5: '2016-07-16',
      6: '2016-07-17'},
     'id': {0: 31, 1: 32, 2: 33, 3: 34, 4: 35, 5: 36, 6: 37},
     'measure': {0: '[2, 5, 3, 3]',
      1: '[3, 5, 3, 3]',
      2: '[2, 1, 2, 2]',
      3: '[2, 6, 3, 3]',
      4: '[39, 31, 73, 34]',
      5: '[3, 2, 3, 3]',
      6: '[3, 8, 3, 3]'},
     'result': {0: 1, 1: 1, 2: 1, 3: 1, 4: 0, 5: 1, 6: 1}}
df = pd.DataFrame(mydict)

我定义了一个简单的函数来计算均值并返回列表。 然后,应用规则循环数据框:

def calc_mean(in_list):
    p0 = round((in_list[0][0] + in_list[1][0] + in_list[2][0])/3,1)
    p1 = round((in_list[0][1] + in_list[1][1] + in_list[2][1])/3,1)
    p2 = round((in_list[0][2] + in_list[1][2] + in_list[2][2])/3,1)
    p3 = round((in_list[0][3] + in_list[1][3] + in_list[2][3])/3,1)
    return [p0, p1, p2, p3]

Solution = []
aux_list = []
for index, row in df.iterrows():
    if index in [0,1,2]:
        Solution.append(row.measure)
        aux_list.append([int(x) for x in row.measure[1:-1].split(', ')])
    else:
        Solution.append('[' +', '.join(map(str, calc_mean(aux_list))) + ']')
        if row.result > 0:
            aux_list.pop(0)
            aux_list.append([int(x) for x in row.measure[1:-1].split(', ')])        
df['Solution'] = Solution

输出为:

在此处输入图片说明

请注意,结果四舍五入到小数点后1位,与您想要的输出有些不同。 对我来说更有意义。

编辑:

作为@Frenchy的注释中的建议,要在前3行中处理result == 0,我们需要对第一个if子句进行一些更改:

if index in [0,1,2] or len(aux_list) <3:
    Solution.append(row.measure)
    if row.result > 0:
        aux_list.append([int(x) for x in row.measure[1:-1].split(', ')])

您可以使用pd.eval从改变strlist ,以适当的list中的数据只有部分measure ,其中result不为0,使用rollingmean ,然后shift了在最后3行,以获得滚动平均值下一行。 一旦您的数据tolist更改为具有valuestolist的列表列表,然后mapstr 最后,您只需要替换前三行并ffill缺失的数据即可:

df.loc[df.result.shift() != 0,'solution'] = list(map(str,
                              pd.DataFrame(pd.eval(df[df.result != 0].measure))
                                .rolling(3).mean().shift().values.tolist()))
df.loc[:2,'solution'] = df.loc[:2,'measure']
df.solution = df.solution.ffill()

这是另一个解决方案:

# get data to reproduce example
from io import StringIO
data = StringIO(""" 
    date;id;measure;result 
    2016-07-11;31;"[2,5,3,3]";1 
    2016-07-12;32;"[3,5,3,3]";1 
    2016-07-13;33;"[2,1,2,2]";1 
    2016-07-14;34;"[2,6,3,3]";1 
    2016-07-15;35;"[39,31,73,34]";0 
    2016-07-16;36;"[3,2,3,3]";1 
    2016-07-17;37;"[3,8,3,3]";1 
    """)  

df = pd.read_csv(data, sep=";")
df
# Out:
#          date  id        measure  result
# 0  2016-07-11  31      [2,5,3,3]       1
# 1  2016-07-12  32      [3,5,3,3]       1
# 2  2016-07-13  33      [2,1,2,2]       1
# 3  2016-07-14  34      [2,6,3,3]       1
# 4  2016-07-15  35  [39,31,73,34]       0
# 5  2016-07-16  36      [3,2,3,3]       1
# 6  2016-07-17  37      [3,8,3,3]       1  

# convert values in measure column to lists
from ast import literal_eval
dm = df['measure'].apply(literal_eval)

# apply rolling mean with period 2 and recollect values into list in column means
df["means"] = dm.apply(pd.Series).rolling(2, min_periods=0).mean().values.tolist()                            

df                                                                                                           
# Out: 
#          date  id        measure  result                     means
# 0  2016-07-11  31      [2,5,3,3]       1      [2.0, 5.0, 3.0, 3.0]
# 1  2016-07-12  32      [3,5,3,3]       1      [2.5, 5.0, 3.0, 3.0]
# 2  2016-07-13  33      [2,1,2,2]       1      [2.5, 3.0, 2.5, 2.5]
# 3  2016-07-14  34      [2,6,3,3]       1      [2.0, 3.5, 2.5, 2.5]
# 4  2016-07-15  35  [39,31,73,34]       0  [20.5, 18.5, 38.0, 18.5]
# 5  2016-07-16  36      [3,2,3,3]       1  [21.0, 16.5, 38.0, 18.5]
# 6  2016-07-17  37      [3,8,3,3]       1      [3.0, 5.0, 3.0, 3.0]

# moving window of size 3
df["means"] = dm.apply(pd.Series).rolling(3, min_periods=0).mean().round(2).values.tolist()
df
# Out: 
#             date  id        measure  result                        means
# 0  2016-07-11  31      [2,5,3,3]       1         [2.0, 5.0, 3.0, 3.0]
# 1  2016-07-12  32      [3,5,3,3]       1         [2.5, 5.0, 3.0, 3.0]
# 2  2016-07-13  33      [2,1,2,2]       1     [2.33, 3.67, 2.67, 2.67]
# 3  2016-07-14  34      [2,6,3,3]       1      [2.33, 4.0, 2.67, 2.67]
# 4  2016-07-15  35  [39,31,73,34]       0   [14.33, 12.67, 26.0, 13.0]
# 5  2016-07-16  36      [3,2,3,3]       1  [14.67, 13.0, 26.33, 13.33]
# 6  2016-07-17  37      [3,8,3,3]       1  [15.0, 13.67, 26.33, 13.33]    

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM