很像Python,但不像Pandas那样令人信服

2024-10-03 17:19:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数据帧,其中每个序列都填充了0和1,如下所示:

flagdf=pd.DataFrame({'a':[1,0,1,0,1,0,0,1], 'b':[0,0,1,0,1,0,1,0]})

现在,根据我所做的一些分析,我需要将一些0更改为1。因此最终的数据帧将是:

final=pd.DataFrame({'a':[1,1,1,0,1,1,1,1], 'b':[1,1,1,0,1,1,1,1]})

显示必须更改的0的分析结果存储在使用多索引构建的第二个数据帧中:

     first  last
a 1      1     1
  5      5     6
b 0      0     1
  5      5     5
  7      7     7

对于每个“a”和“b”,我都有需要更改的0的第一个和最后一个索引。你知道吗

第一个问题:多索引数据帧中的第二个索引等于序列“First”。我最初试图直接使用它,但我发现处理两个序列比处理索引和序列更容易。我错过什么了吗?你知道吗

以下是执行此任务的代码:

def change_one_value_one_column(flagdf,col_name,event):
    flagdf[col_name].iloc[event]=1

def change_val_column(col_name, tochange, flagdf):
    col_tochange=tochange.ix[col_name]
    tomod=col_tochange[['first','last']].values
    iter_tomod=[xrange(el[0],el[1]+1) for el in tomod]
    [change_one_value_one_column(flagdf,col_name,event) for iterel in iter_tomod for event in iterel]

[change_val_colmun(col_name) for col_name in flagdf.columns]

第二个问题:我真的认为列表理解总是好的,但是在这种情况下,当我为列表理解编写一个函数时,我有一些疑问。这真的是最好的选择吗?你知道吗

第三个问题:我认为这段代码是相当python的,但我并不为此感到骄傲,因为最后一个列表理解是在dataframe系列中运行的:在我看来,使用apply方法会更好(但我不知道怎么做)。没有什么真正的理由(除了优雅)我应该努力做这些改变吗?你知道吗


Tags: 数据nameinevent列表forcolumn序列
2条回答

如果我停留在python中对行进行迭代,我更喜欢使用zip/izip作为第一步。你知道吗

for col, start, end in izip(to_change.index.get_level_values(0), tochange['first'], tochange['last']):
     flagdf.loc[start:end, col] = 1

简单快速。你知道吗

为了回答关于耗尽迭代器的部分,我认为您有一些pythonic的选择(所有这些我都喜欢列表理解):

# the easiest, and most readable
for col_name in flagdf.columns:
    change_val_column(col_name)

# consume/exhaust an iterator using built-in any (assuming each call returns None)
any(change_val_colmun(col_name) for col_name in flagdf.columns)

# use itertools' consume recipe
consume(change_val_colmun(col_name) for col_name in flagdf.columns)

参见consume recipe from itertools

然而,当在numpy/pandas中做这种事情时,你应该问自己“我能在这里垂直化/使用索引吗?”。如果可以的话,你的代码通常会更快更可读。你知道吗

我认为,在这种情况下,您可以通过执行以下操作来移除一级循环:

def change_val_column(col_name, tochange, flagdf):
    col_tochange = tochange.ix[col_name]  # Note: you're accessing index not column here??
    tomod = col_tochange[['first','last']].values
    for i, j in tomod:
        flag_df.loc[i:j, col_name] = 1

你甚至可以移除for循环,但是不清楚这里的意图是什么。。。你知道吗

相关问题 更多 >