在python数据帧中添加时间序列强度的廉价方法
我试图使用Python的Pandas.DataFrame对在不同时间改变状态的函数求和(并绘制)总数。例如: 假设我们有3个人,他们的状态可以是a)什么都不拿,b)拿着5磅重,c)拿着10磅重。随着时间的推移,这些人拿起重物放下来。我想画出总重量。因此,鉴于: 我残忍的止赎企图:在python数据帧中添加时间序列强度的廉价方法,python,plot,pandas,time-series,dataframe,Python,Plot,Pandas,Time Series,Dataframe,我试图使用Python的Pandas.DataFrame对在不同时间改变状态的函数求和(并绘制)总数。例如: 假设我们有3个人,他们的状态可以是a)什么都不拿,b)拿着5磅重,c)拿着10磅重。随着时间的推移,这些人拿起重物放下来。我想画出总重量。因此,鉴于: 我残忍的止赎企图: import pandas as ps import math import numpy as np person1=[3,0,10,10,10,10,10] person2=[4,0,20,20,25,25,40]
import pandas as ps
import math
import numpy as np
person1=[3,0,10,10,10,10,10]
person2=[4,0,20,20,25,25,40]
person3=[5,0,5,5,15,15,40]
allPeopleDf=ps.DataFrame(np.array(zip(person1,person2,person3)).T)
allPeopleDf.columns=['count','start1', 'end1', 'start2', 'end2', 'start3','end3']
allPeopleDfNoCount=allPeopleDf[['start1', 'end1', 'start2', 'end2', 'start3','end3']]
uniqueTimes=sorted(ps.unique(allPeopleDfNoCount.values.ravel()))
possibleStates=[-1,0,1,2] #extra state 0 for initialization
stateData={}
comboStates={}
#initialize dict to add up all of the stateData
for time in uniqueTimes:
comboStates[time]=0.0
allPeopleDf['track']=-1
allPeopleDf['status']=-1
numberState=len(possibleStates)
starti=-1
endi=0
startState=0
for i in range(3):
starti=starti+2
print starti
endi=endi+2
for time in uniqueTimes:
def helper(row):
start=row[starti]
end=row[endi]
track=row[7]
if start <= time and time < end:
return possibleStates[i+1]
else:
return possibleStates[0]
def trackHelp(row):
status=row[8]
track=row[7]
if track<=status:
return status
else:
return track
def Multiplier(row):
x=row[8]
if x==0:
return 0.0*row[0]
if x==1:
return 5.0*row[0]
if x==2:
return 10.0*row[0]
if x==-1:#numeric place holder for non-contributing
return 0.0*row[0]
allPeopleDf['status']=allPeopleDf.apply(helper,axis=1)
allPeopleDf['track']=allPeopleDf.apply(trackHelp,axis=1)
stateData[time]=allPeopleDf.apply(Multiplier,axis=1).sum()
for k,v in stateData.iteritems():
comboStates[k]=comboStates.get(k,0)+v
print allPeopleDf
print stateData
print comboStates
TypeError:-:“str”和“int”的操作数类型不受支持
结束编辑似乎是
.sum()
的作用:
In [10]:
allPeopleDf.sum()
Out[10]:
aStart 0
aEnd 35
bStart 35
bEnd 50
cStart 50
cEnd 90
dtype: int32
以钢琴键为例,假设有三个键,强度为30级 我将尝试以以下格式保存数据:
import pandas as pd
df = pd.DataFrame([[10,'A',5],
[10,'B',7],
[13,'C',10],
[15,'A',15],
[20,'A',7],
[23,'C',0]], columns=["time", "key", "intensity"])
time key intensity
0 10 A 5
1 10 B 7
2 13 C 10
3 15 A 15
4 20 A 7
5 23 C 0
您可以在其中记录任何关键点的强度变化。从这里,您可以获得每个单独关键点的笛卡尔坐标,即(时间、强度)
对
df[df.key=="A"].drop('key',1)
time intensity
0 10 5
3 15 15
4 20 7
然后,您可以轻松创建一个新列increment
,该列将指示该关键点在该时间点发生的强度变化(intensity
仅指示强度的新值)
然后,使用这个新列,您可以生成(时间,总强度)
对以用作笛卡尔坐标
df.groupby("time").sum()["increment"].cumsum()
time
10 12
13 22
15 32
20 24
23 14
dtype: int64
编辑:应用相关的特定数据
假设数据以值列表的形式出现,从元素id(person/piano键)开始,然后是一个因子乘以该元素的测量重量/强度,然后是一对时间值,指示一系列已知状态(携带重量/发射强度)的开始和结束不确定数据格式是否正确。根据你的问题:
data1=['person1',3,0.0,10.0,10.0,10.0,10.0,10.0]
data2=['person2',4,0,20,20,25,25,40]
data3=['person3',5,0,5,5,15,15,40]
如果我们知道每个状态的权重/强度,我们可以定义:
known_states = [5, 10, 15]
DF_columns = ["time", "id", "intensity"]
然后,加载数据的最简单方法包括以下函数:
import pandas as pd
def read_data(data, states, columns):
id = data[0]
factor = data[1]
reshaped_data = []
for i in xrange(len(states)):
j += 2+2*i
if not data[j] == data[j+1]:
reshaped_data.append([data[j], id, factor*states[i]])
reshaped_data.append([data[j+1], id, -1*factor*states[i]])
return pd.DataFrame(reshaped_data, columns=columns)
请注意,if not data[j]==data[j+1]:
避免在给定状态的开始时间和结束时间相等时将数据加载到数据帧中(似乎没有信息,并且无论如何也不会出现在绘图中)。但是如果你还想要这些条目,就把它拿出来
然后,加载数据:
df = read_data(data1, known_states, DF_columns)
df = df.append(read_data(data2, known_states, DF_columns), ignore_index=True)
df = df.append(read_data(data3, known_states, DF_columns), ignore_index=True)
# and so on...
然后你在这个答案的开头是对的(当然用id和id替换key)我喜欢使用.sum(),谢谢。在我的示例中,为了再现黑线,我认为需要每个时间步的强度值之和:0,5,15,20,25,40。因此,在我的重量示例中,黑图可能由以下笛卡尔点组成:(0,0磅)(5,0磅)(5,5磅)(15,5磅)(15,5磅)(15,10磅)(20,10磅)(20,15磅)(25,15磅)(25,20磅)(40,20磅)。我将编辑问题以更好地反映这一点。我想这就是我一直在寻找的!我会检查这个,发布我的蛮力解决方案进行比较,然后奖励赏金。谢谢。我在上面添加了您答案的实现。我在实现转换函数时出错:…不支持的操作数类型-:'str'和'int'。我是python新手,仍然在消化df[“increment”]行。关于这个错误的来源有什么想法吗?我在最后一行代码中添加了一个更正。我在代码测试中使用了无意义的列名,如“A”、“C”等,然后我忘记了将“C”改为“increment”。现在它被纠正了。然而,这并不是导致错误的原因。我评论了你的问题,试图澄清它!:)这太棒了。谢谢。什么是“开始1”、“结束1”等等?时代?当权重/音符强度可能发生变化时,你真的只有几次标记时间吗?还是更像是一个连续体?我的意思是,“start1”标签对你有意义吗,还是只是问题简化的一部分?在我的回答中,我假设您可以将数据视为第二个23人2将其权重更改为15。。。但是我们可以调整它……另外,每个列表的初始值是什么意思(
3
、4
和5
)?我原以为其余的值代表了那个人在每个时间点所承受的权重,但看到allPeopleDf.columns=['intensity','id','timeid','time'的输出后,我感到困惑.
试着解释真实数据是如何组织的,以便我们可以调整代码以适应它。要继续钢琴示例:startx/endx指的是一个键以一定强度弹奏的开始和结束时间。start1/end1可能是每个关键点以强度0播放的时间,start2/end2可能是每个关键点以强度x播放的时间,等等。很抱歉与3,4,5混淆-这些是应用于最终结果的权重。例如,假设音符A、B和C的强度相同,也许一个人会更容易听到C,所以我考虑了一些加权因子。我将把它留在示例中,这样我就不会因为删除它而引起更多的混乱,但请随意忽略它。答案已编辑。我想现在应该没事了
import pandas as pd
def read_data(data, states, columns):
id = data[0]
factor = data[1]
reshaped_data = []
for i in xrange(len(states)):
j += 2+2*i
if not data[j] == data[j+1]:
reshaped_data.append([data[j], id, factor*states[i]])
reshaped_data.append([data[j+1], id, -1*factor*states[i]])
return pd.DataFrame(reshaped_data, columns=columns)
df = read_data(data1, known_states, DF_columns)
df = df.append(read_data(data2, known_states, DF_columns), ignore_index=True)
df = df.append(read_data(data3, known_states, DF_columns), ignore_index=True)
# and so on...