根据行中的值在特定位置将列表作为数据框中的列插入

inserting a list as a column in dataframe at specific location depending on value in row

所以我有一个数据框(tsv/csv 文件),使用 numpy、pandas 和 statsmodels。

在一列中"medianame"屏幕上会出现媒体名称(一种刺激)(这种刺激是移动的。每行代表一个时间戳)。

每当此列中出现特定媒体名称时(对于此示例,假设为 "stimulus1"),就该插入一个列表,假设有 5 个数字在另一列中,从这一行开始。

列中的其他项目需要为空 (np.nan)。

另一个要求是必须在名称出现 "again" 的任何情况下插入 "medianame" 列。因此,列表中的项目数可能少于媒体名称连续出现的次数(请参见下面示例中的第一种情况)。

如果列表中的项数超过了medianame连续出现的次数,则必须提前截断(见下例中的第二种情况)。

示例:

List1 = [5, 7, 1, 8, 9] # to be inserted in column "position"
                        # when medianame "stimulus1" appears in column "medianame"

medianame
stimulus0
stimulus0
stimulus0
stimulus0
stimulus0
stimulus0
NaN
stimulus1
stimulus1
stimulus1
stimulus1
stimulus1
stimulus1
stimulus1
stimulus1
stimulus1
stimulus1
NaN
stimulus2
stimulus2
stimulus2
stimulus2
stimulus2
NaN
stimulus1
stimulus1
stimulus1

在正确的位置添加后,希望它看起来像:

medianame     position
stimulus0     NaN
stimulus0     NaN
stimulus0     NaN
stimulus0     NaN
stimulus0     NaN
stimulus0     NaN
NaN           NaN
stimulus1     5
stimulus1     7
stimulus1     1
stimulus1     8
stimulus1     9
stimulus1     NaN
stimulus1     NaN
stimulus1     NaN
stimulus1     NaN
stimulus1     NaN
NaN           NaN
stimulus2     NaN
stimulus2     NaN
stimulus2     NaN
stimulus2     NaN
stimulus2     NaN
NaN           NaN
stimulus1     5
stimulus1     7
stimulus1     1

这是使用 mergegroupbycumsum 和 pd.Series 构造函数的一种方法:

df.assign(key = df.groupby((df['medianame'] != 'stimulus1').cumsum()).cumcount())\
  .merge(pd.Series(List1, index=range(1,len(List1)+1)).rename('position'), 
         left_on='key', 
         right_index=True, 
         how='left')\
  .drop('key', axis=1)

输出:

    medianame  position
0   stimulus0       NaN
1   stimulus0       NaN
2   stimulus0       NaN
3   stimulus0       NaN
4   stimulus0       NaN
5   stimulus0       NaN
6         NaN       NaN
7   stimulus1       5.0
8   stimulus1       7.0
9   stimulus1       1.0
10  stimulus1       8.0
11  stimulus1       9.0
12  stimulus1       NaN
13  stimulus1       NaN
14  stimulus1       NaN
15  stimulus1       NaN
16  stimulus1       NaN
17        NaN       NaN
18  stimulus2       NaN
19  stimulus2       NaN
20  stimulus2       NaN
21  stimulus2       NaN
22  stimulus2       NaN
23        NaN       NaN
24  stimulus1       5.0
25  stimulus1       7.0
26  stimulus1       1.0

详情

创建一个系列,s,索引范围从 1:

s = pd.Series(List1, index=range(1,len(List1)+1)).rename('position')

输出:

1    5
2    7
3    1
4    8
5    9
Name: position, dtype: int64

现在,让我们将该系列连接到 stimulus1 所在的数据帧 df,但首先我们需要在 df 上创建一个连接键。

df_key = df.assign(key = df.groupby((df['medianame'] != 'stimulus1').cumsum()).cumcount())

输出:

    medianame  key
0   stimulus0    0
1   stimulus0    0
2   stimulus0    0
3   stimulus0    0
4   stimulus0    0
5   stimulus0    0
6         NaN    0
7   stimulus1    1
8   stimulus1    2
9   stimulus1    3
10  stimulus1    4
11  stimulus1    5
12  stimulus1    6
13  stimulus1    7
14  stimulus1    8
15  stimulus1    9
16  stimulus1   10
17        NaN    0
18  stimulus2    0
19  stimulus2    0
20  stimulus2    0
21  stimulus2    0
22  stimulus2    0
23        NaN    0
24  stimulus1    1
25  stimulus1    2
26  stimulus1    3

最后,将 df_key 与键上的 s how='left' 和 s.index:

合并
df_key.merge(s, how='left', left_on='key', right_index=True)

输出:

    medianame  key  position
0   stimulus0    0       NaN
1   stimulus0    0       NaN
2   stimulus0    0       NaN
3   stimulus0    0       NaN
4   stimulus0    0       NaN
5   stimulus0    0       NaN
6         NaN    0       NaN
7   stimulus1    1       5.0
8   stimulus1    2       7.0
9   stimulus1    3       1.0
10  stimulus1    4       8.0
11  stimulus1    5       9.0
12  stimulus1    6       NaN
13  stimulus1    7       NaN
14  stimulus1    8       NaN
15  stimulus1    9       NaN
16  stimulus1   10       NaN
17        NaN    0       NaN
18  stimulus2    0       NaN
19  stimulus2    0       NaN
20  stimulus2    0       NaN
21  stimulus2    0       NaN
22  stimulus2    0       NaN
23        NaN    0       NaN
24  stimulus1    1       5.0
25  stimulus1    2       7.0
26  stimulus1    3       1.0

并且,如果需要,您可以删除该键列。