考虑这个简单的例子
import pandas as pd
df = pd.DataFrame({'one' : [1,2,3],
'two' : [1,0,0]})
df
Out[9]:
one two
0 1 1
1 2 0
2 3 0
我想编写一个函数,将数据框df
和列mycol
作为输入。
现在可行:
df.groupby('one').two.sum()
Out[10]:
one
1 1
2 0
3 0
Name: two, dtype: int64
这也有效:
def okidoki(df,mycol):
return df.groupby('one')[mycol].sum()
okidoki(df, 'two')
Out[11]:
one
1 1
2 0
3 0
Name: two, dtype: int64
但是失败
def megabug(df,mycol):
return df.groupby('one').mycol.sum()
megabug(df, 'two')
AttributeError: 'DataFrameGroupBy' object has no attribute 'mycol'
这里有什么问题?
我担心okidoki
使用某些链接可能会产生一些微妙的错误(https://pandas.pydata.org/pandas-docs/stable/indexing.html#why-does-assignment-fail-when-using-chained-indexing)。
如何保持语法groupby('one').mycol
?可以将mycol
字符串转换为可能以这种方式工作的字符串吗?
谢谢!
答案 0 :(得分:3)
我认为您需要function myBreakFunc(str, n, x) {
var pattern = RegExp(`[^${x}]{${n}}(?=[^${x}])`, 'g');
return str.replace(pattern, '$&' + x)
}
var res = myBreakFunc("One two three four", 3, ' ');
console.log(res);
按列名选择列,这是选择列的一般解决方案,因为按属性选择有很多exceptions:
- 只有当index元素是有效的python标识符时才可以使用此访问权限,例如s.1是不允许的。有关有效标识符的说明,请参见此处。
- 如果该属性与现有方法名称冲突,则该属性将不可用,例如: s.min是不允许的。
- 同样,如果该属性与以下任何列表冲突,则该属性将不可用:index,major_axis,minor_axis,items,labels。
- 在任何这些情况下,标准索引仍然有效,例如: s [' 1'],s [' min']和s [' index']将访问相应的元素或列。
[]
答案 1 :(得分:3)
您传递一个字符串作为第二个参数。实际上,您正在尝试执行以下操作:
df.'two'
哪种语法无效。如果您尝试动态访问某列,则需要使用索引表示法[...]
,因为点/属性访问器表示法不适用于动态访问。
可以自行动态访问。例如,您可以使用getattr
(但我不要推荐这个,它是反模式):
In [674]: df
Out[674]:
one two
0 1 1
1 2 0
2 3 0
In [675]: getattr(df, 'one')
Out[675]:
0 1
1 2
2 3
Name: one, dtype: int64
可以通过groupby调用按属性动态选择,例如:
In [677]: getattr(df.groupby('one'), mycol).sum()
Out[677]:
one
1 1
2 0
3 0
Name: two, dtype: int64
但是没有这样做。这是一种可怕的反模式,比df.groupby('one')[mycol].sum()
更难以理解。