我想从B列创建C列,而没有for循环...
数据框:
title = 'Daily Log ';
value = $(txt).val().replace(/\n/g, '</tspan><tspan x="0" dy="1.2em">');
numberOfLines = $(txt).val().split("\n").length;
txt = '<text transform="translate(' + 560 + ', ' + 30 + ')"><tspan x="0" dy="1.2em">' + title + '</br>' + ' at ' + '</tspan></text>';
if (i == 0) {
top += 100
svgArr.push(txt);
}
i += 1;
基本上,我想获取B中下一个更改的值并将其设置为新的列C。
到目前为止,答案来自:Determining when a column value changes in pandas dataframe 我有:
# | A | B | C
--+-----+----+-----
1 | 2 | 3 | 4
2 | 3 | 3 | 4
3 | 4 | 4 | 6
4 | 5 | 4 | 6
5 | 5 | 4 | 6
6 | 3 | 6 | 2
7 | 2 | 6 | 2
8 | 4 | 2 | 3 #< --- loop back around if possible (B value at index 1)
但是在那之后,我不确定如何在不使用循环的情况下创建C ...
编辑: @(Ayoub ZAROU)的答案回答了我的原始问题,但是,如果我们假设数据中存在循环,我注意到我的示例数据框未涵盖所有情况:
df_filtered = df[df['B'].diff() != 0]
在这种情况下,如果3的最后一个片段被认为是3的第一个片段的一部分,那么使用此解决方案,C中的最后两个值将是错误的。
一个简单的解决方法是将最后几个元素移到列表的开头,反之亦然
答案 0 :(得分:3)
您可以尝试,请注意np.roll
与大熊猫的转变相同,唯一的不同是,它允许您将值翻转,
在下面的内容中,c
为您提供了没有变化的索引
c = (df.B.diff(-1) == 0)
c
Out[104]:
0 True
1 False
2 True
3 True
4 False
5 True
6 False
7 False
Name: B, dtype: bool
我们然后将其中的值设置为使用np.roll产生的B
列上的下一个值,并使用pandas.Series.where
进行设置,请注意,在何处更改值,在何处更改列{{1 }}不是c
,
True
然后我们在熊猫上使用df['C'] = np.nan
df['C'] = df.C.where(c, np.roll(df.B, -1))
df.C
Out[107]:
0 NaN
1 4.0
2 NaN
3 NaN
4 6.0
5 NaN
6 2.0
7 3.0
Name: C, dtype: float64
填充其余行,并将其强制转换为bfill
'列B
,
因此,在全球范围内
dtype
c = (df.B.diff(-1) == 0)
df['C'] = np.nan
df['C'] = df.C.where(c, np.roll(df.B, -1)).bfill().astype(df.B.dtype)
答案 1 :(得分:3)
另一种方法是获取值更改:
In [11]: changes = (df.B != df.B.shift()).cumsum()
In [12]: changes
Out[12]:
0 1
1 1
2 2
3 2
4 2
5 3
6 3
7 4
Name: B, dtype: int64
和一个查找图:
In [13]: lookup = df.B[(df.B != df.B.shift())]
In [14]: lookup.at[len(lookup)] = df.B.iloc[0]
In [15]: lookup
Out[15]:
0 3
2 4
5 6
7 2
4 3
Name: B, dtype: int64
然后使用它们查找“下一个”:
In [16]: lookup.iloc[changes]
Out[16]:
2 4
2 4
5 6
5 6
5 6
7 2
7 2
4 3
Name: B, dtype: int64
要创建列,您需要忽略索引中的重复项:
In [17]: df["C"] = lookup.iloc[changes].values
答案 2 :(得分:1)
移动B
,按原始df.B
分组。最后,transform
和fillna
df.B.shift(-1).groupby([df.B]).transform('last').fillna(df.at[1,'B'])
Out[22]:
1 4.0
2 4.0
3 6.0
4 6.0
5 6.0
6 2.0
7 2.0
8 3.0
Name: B, dtype: float64
您还可以将np.roll
与assign
一起使用,以创建列C
并在B
上分组transform
和C
。这样,您就不需要shift
和fillna
df.assign(C=np.roll(df.B,-1)).groupby('B').C.transform('last')
Out[36]:
1 4
2 4
3 6
4 6
5 6
6 2
7 2
8 3
Name: C, dtype: int64
答案 3 :(得分:0)
您可以使用pandas.DataFrame.shift。 让我们用一个例子来做。考虑一个数据框:
a = pd.DataFrame(columns=['a','b'], data=[[1,2], [5,6], [5,3]])
print(a)
Out[0]:
a b
0 1 2
1 5 6
2 5 3
然后使用shift创建列'c'
a['c'] = a.b.shift(1)
Out[1]:
a b c
0 1 2 NaN
1 5 6 2.0
2 5 3 6.0
然后用列'c'减去列'b'。
a.c = a.b - a.c
Out[2]:
a b c
0 1 2 NaN
1 5 6 4.0
2 5 3 -3.0
这将为您提供下一个更改的值,即列“ b”和“ c”之间的差。 希望对您有所帮助。