id stage_seq
1 [(A,1), (B,3), (C,5)]
2 [(B,2), (C,2), (E,6)]
3 [(B,2), (C,1), (D,2), (E,3)]
我想删除最后一个阶段是E的记录,而第二阶段到最后一个阶段的记录是D(即在上面的数据框中删除记录id = 3)。这是我的代码:
df = df[(df.stage_seq[-1][0] != "E") | (df.stage_seq[-2][0] != "D")]
但我收到以下错误:
df = df [(df.stage_seq [-1] [0]!=" E")| (df.stage_seq [-2] [0]!=" D")]
KeyError:-1
处理值为列表的pandas列的正确方法是什么?
答案 0 :(得分:3)
使用.str[]
选择第一个元组,然后使用元组中的值,因为list
和tuple
是string
s之类的迭代:
df = df[(df.stage_seq.str[-1].str[0] != "E") | (df.stage_seq.str[-2].str[0] != "D")]
print (df)
id stage_seq
0 1 [(A, 1), (B, 3), (C, 5)]
1 2 [(B, 2), (C, 2), (E, 6)]
<强>详情:
print(df.stage_seq.str[-1])
0 (C, 5)
1 (E, 6)
2 (E, 3)
Name: stage_seq, dtype: object
print(df.stage_seq.str[-1].str[0])
0 C
1 E
2 E
Name: stage_seq, dtype: object
替代解决方案,如果NaN
没有list comprehension
且位置中存在值:
df = df[[x[-1][0] != 'E' or x[-2][0] != 'D' for x in df.stage_seq]]
print (df)
id stage_seq
0 1 [(A, 1), (B, 3), (C, 5)]
1 2 [(B, 2), (C, 2), (E, 6)]
第一个解决方案也工作,如果想选择不存在的元组:
print(df.stage_seq.str[3])
0 NaN
1 NaN
2 (E, 3)
Name: stage_seq, dtype: object
print(df.stage_seq.str[3].str[0])
0 NaN
1 NaN
2 E
Name: stage_seq, dtype: object
print(df.stage_seq.str[3].str[0] == 'E')
0 False
1 False
2 True
Name: stage_seq, dtype: bool
print ([x[3][0] != 'E' != 'D' for x in df.stage_seq])
IndexError:列表索引超出范围
答案 1 :(得分:2)
如果您想在没有新列的情况下在一行中执行此操作,则可以执行以下操作:
df = df[df.stage_seq.apply(lambda x: x[-1][0] != 'E') | \
df.stage_seq.apply(lambda x: x[-2][0] != 'D')]
结果是:
id stage_seq
0 1 [(A, 1), (B, 3), (C, 5)]
1 2 [(B, 2), (C, 2), (E, 6)]
您的问题是您尝试访问df.stage_seq
中的列表,但df.column[x][y]
语法不会这样做。相反,您可以使用lambda函数访问df.stage_seq
的每个单元格的内容,然后然后选择所需的列表元素。请注意,这假设实际数据帧中的所有单元格实际上都具有这些位置的值。
答案 2 :(得分:0)
你需要这样的东西:
创建一个仅包含阶段的新列:
df['stage'] = df['stage_seq'].apply(lambda x: "".join(w for w,x in x))
为最后一个和第二个最后一个阶段创建两个单独的列
df['last_stage'] = df['stage'].apply(lambda x: x[-1])
df['2ndlast_stage'] = df['stage'].apply(lambda x: x[-2])
过滤数据框
df1=df[~((df['last_stage'] == 'E') & (df['2ndlast_stage'] == 'D'))]