我想比较几对pandas
数据帧中的列,并将共享值写入空列表。我已经编写了一个可以使用一对数据帧执行此操作的函数,但我似乎无法将其扩展。
def parser(dataframe1,dataframe2,emptylist):
for i1 in dataframe1['POS']:
for i2 in dataframe2['POS']:
if i1 == i2:
emptylist.append(i1)
'POS'
是两个pandas
数据框中的列标题。
我已为此函数的每个输入值列出了变量名称,例如
dataframe1_names=['name1','name2',etc...]
dataframe2_names=['name1','name2',etc...]
emptylist_names=['name1','name2',etc...]
其中列表的每个元素都是一个包含变量名称的字符串(前两个是pandas数据帧,最后一个是空列表)。
我尝试使用以下代码遍历这些列表:
import itertools
for a, b, c in zip(range(len(dataframe1_names)), range(len(dataframe2_names)), range(len(emptylist_names))):
parser(dataframe1_names[a],dataframe2_names[b],emptylist_names[c])
但这会返回TypeError: string indices must be integers
。
我认为这个错误来自于传递函数一个包含变量名而不是变量名本身的字符串。是否有另一种方法可以自动方式将多个变量传递给函数?
感谢您的帮助!
答案 0 :(得分:0)
你有使用对象名字符串,而不只是对象本身吗?如果你这样做
dataframes1=[name1,name2,...]
dataframes2=[name1,name2,...]
emptylists=[name1,name2,...]
然后你可以做
for a,b,c in zip( dataframes1, dataframes2, emptylists ):
parser(a,b,c)
顺便提一下,你这样做的方式真的很迂回,而且我已经改变了一点。我只是遍历列表(以及对象)本身,而不是获取for语句的索引列表。这更紧凑,更容易理解。就此而言,您是否需要输入空列表作为参数(例如,它们可能始终不为空)?并且你的解析器代码虽然正确,但根本没有充分利用pandas,而且速度很慢:比较列,你可以简单地做dataframe1['COL'] == dataframe2['COL']
,这将给你一个布尔系列价值相等的地方。然后,您可以使用它来索引数据帧,以获取共享值。它作为数据框或系列出现,但它很容易转换为列表。因此,如果您不需要创建"空列表,那么您的解析器功能可以简化为以下内容。别的第一个:
def parser( df1, df2 ):
return list( df1['COL'][ df1['COL']==df2['COL'] ] )
这会快得多,但是当它返回列表时,你必须对它做一些事情,所以在你的情况下,你会做类似的事情:
sharedlists = [ parser(a,b) for a,b in zip( dataframes1, dataframes2 ) ]
如果必须使用变量名称,则以下非常不安全的类代码会将您的名称列表转换为对象列表(您需要执行此操作)每个列表都有这个):
dataframes1 = [ eval(name) for name in dataframe1_names ]
如果这只是您在翻译中进行的数字工作,eval
没问题,但对于您发布的任何代码,它都非常不安全:它会评估传递给它的字符串中的代码,从而允许任意代码执行。
答案 1 :(得分:0)
这听起来像。query()
的用例query()的用例是拥有DataFrame的集合 具有列名(或索引级别/名称)子集的对象 共同。您可以将相同的查询传递给两个帧而不必 指定您对查询感兴趣的帧
map(lambda frame: frame.query(expr), [df, df2])
答案 2 :(得分:0)
如果您有两个以上DataFrame
个对象,您在寻找什么样的输出?在只有两个的情况下,以下行将完成parser
函数的作用:
common = df1[df1["fieldname"] == df2["fieldname"]]["fieldname"]
除了common
本身就是DataFrame
个对象,而不是列表,但您可以通过list(common)
轻松地从中获取列表。
如果您正在寻找一个能够接收任意数量的DataFrame并在每个字段的某些字段中返回常用值列表的函数,您可以执行以下操作:
from itertools import combinations
def common_lists(field, *dfs):
return [df1[df1[field] == df2[field]][field] for df1, df2 in combinations(dfs, 2)]
有关从DataFrame获取列表的相同协议适用于此处,因为您将获得DataFrame列表。
就这一点而言:
import itertools
for a, b, c in zip(range(len(dataframe1_names)), range(len(dataframe2_names)), range(len(emptylist_names))):
parser(dataframe1_names[a],dataframe2_names[b],emptylist_names[c])
您正在创建的列表如下所示:
[(0,0,0), (1,1,1), ... (n,n,n)]
其中n
是dataframe1_names
,dataframe2_names
和emptylist_names
中最短的长度。所以在循环的第一次迭代中,你有a == b == c == 0
,并且你正在使用这些值来索引数据框变量名的数组,所以你要调用parser("name1", "name1", "name1")
,而不是传递它的字符串大熊猫DataFrame
个对象。您的解析器函数需要DataFrame
个对象,因此当您尝试调用dataframe1["POS"]
dataframe1
为字符串"name1"
时,它会成为barfs。