【问题标题】:filling new dataframe column using corresponding past indices values and specific unique column values使用相应的过去索引值和特定的唯一列值填充新的数据框列
【发布时间】:2018-07-11 06:19:59
【问题描述】:

我想知道是否有一种优雅的做事方式,我做了很长时间并且我相信非常粗暴的方式。假设我们有一个数据框,其中有两列:'col1','col2'。行数为 13。“Col1”包含三个变量:“a”、“b”和“c”。 'col2' 包含随机数值。现在我想创建一个名为“teststat”的新列,其中包含上次发生时“col1”中的变量包含在“col2”中的值,或者如果这是第一次出现,则等于当前值。例如,如果“a”出现在第 0、1、4、6 和 12 行,并且这些索引位置的 col2 值为 32、432、56、4 和 34,则这些位置的测试统计值应为 32, 32、432、56 和 4。

我想要的样本数据集:

index   col1    teststat    col2
  0      a         32.0       32
  1      a         32.0      432
  2      b        433.0      433
  3      c          4.0        4
  4      a        432.0       56
  5      c          4.0       64
  6      a         56.0        4
  7      b        433.0      535
  8      c         64.0      643
  9      c        643.0      356
 10      b        535.0       32
 11      b         32.0      535
 12      a          4.0       34

我使用了以下代码,它使用了存储“a”、“b”、“c”中特定值的索引的逻辑,然后使用 for 循环编写单独的代码,但我可以看到这可以在扩大规模时成为一个问题,例如,如果 'col1' 中只有 3 个唯一值,我们有 500 多个单独的唯一值。我想要一个关于该场景可以做什么的解决方案/逻辑。我在下面添加了代码:

细胞[1]

for vals in list(df['col1'].unique()):
    if vals=='a':
        idxa = df.index[df['col1']=='a']
    if vals=='b':
        idxb = df.index[df['col1']=='b']
    if vals=='c':
        idxc = df.index[df['col1']=='c']    

细胞[2]

for i in range(len(idxa)):
    if i==0:
        df.loc[idxa[i],'test_stat']=df.loc[idxa[i],'col2']
    else:
        df.loc[idxa[i],'test_stat']=df.loc[idxa[i-1],'col2']


for i in range(len(idxb)):
    if i==0:
        df.loc[idxb[i],'test_stat']=df.loc[idxb[i],'col2']
else:
    df.loc[idxb[i],'test_stat']=df.loc[idxb[i-1],'col2']

for i in range(len(idxc)):
    if i==0:
        df.loc[idxc[i],'test_stat']=df.loc[idxc[i],'col2']
    else:
        df.loc[idxc[i],'test_stat']=df.loc[idxc[i-1],'col2']        

有没有更优雅/更好的方法来做到这一点?任何想法/帮助将不胜感激。

【问题讨论】:

    标签: python python-3.x pandas for-loop dataframe


    【解决方案1】:

    一种方法是使用groupbyshift

    df['teststat'] = df.groupby('col1')['col2'].shift(1).fillna(df['col2'])
    
    print(df[['col1', 'teststat', 'col2']])
    
        col1    teststat    col2
    0      a        32.0      32
    1      a        32.0     432
    2      b       433.0     433
    3      c         4.0       4
    4      a       432.0      56
    5      c         4.0      64
    6      a        56.0       4
    7      b       433.0     535
    8      c        64.0     643
    9      c       643.0     356
    10     b       535.0      32
    11     b        32.0     535
    12     a         4.0      34
    

    编辑

    对于您添加的问题:

    假设,我想要另一列“teststat2”,它给出了“col1”中特定值的最后 2 个值之间的差异。

    您只需执行以下操作。

    df['teststat2'] = df['col2'] - df['teststat']
    df.loc[df['teststat2'] == 0, 'teststat2'] = df['col2']
    print(df)
    
        col1    teststat    col2    teststat2
    0      a        32.0      32         32.0
    1      a        32.0     432        400.0
    2      b       433.0     433        433.0
    3      c         4.0       4          4.0
    4      a       432.0      56       -376.0
    5      c         4.0      64         60.0
    6      a        56.0       4        -52.0
    7      b       433.0     535        102.0
    8      c        64.0     643        579.0
    9      c       643.0     356       -287.0
    10     b       535.0      32       -503.0
    11     b        32.0     535        503.0
    12     a         4.0      34         30.0
    

    【讨论】:

    • 好答案,.shift(1) 应该是 .shift() :)
    • 非常感谢您的解决方案。它有效,从我上面可以理解的是,您首先将索引移动 1 以根据 col1 对 col2 值进行分组,然后将这些值填充到“teststat”列中。好的,现在我有另一个问题,这是对此的扩展。假设,我想要另一列“teststat2”,它给出了“col1”中特定值的最后两个值之间的差异。如何解决这个问题,据我了解 shift 只是移动索引而不是存储该索引。谢谢你的帮助顺便说一句
    • like 'a' 出现在第 0、1、4、6 和 12 行,并且这些索引位置的 col2 值为 32、432、56、4 和 34,那么 teststat2 值应为 32(= 32),400(=432-32),-376(=56-432) 和 30(=34-4)。
    • 除非我遗漏了什么,否则这似乎与从df['col2] 中减去df['teststat] 相同。然后您可以更新 df['teststat2] 为 0 的值。请参阅我的编辑。
    • 是的,Ben 刚才检查了您的编辑。奇迹般有效。谢谢你的帮助。但现在我必须加强对变换和分组操作的控制。确实很方便。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    • 2017-11-16
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多