我有一个熊猫数据框架,df_test。它包含一个列'size',以字节为单位表示大小。我已经计算了KB, MB和GB使用以下代码:
df_test = pd.DataFrame([
{'dir': '/Users/uname1', 'size': 994933},
{'dir': '/Users/uname2', 'size': 109338711},
])
df_test['size_kb'] = df_test['size'].astype(int).apply(lambda x: locale.format("%.1f", x / 1024.0, grouping=True) + ' KB')
df_test['size_mb'] = df_test['size'].astype(int).apply(lambda x: locale.format("%.1f", x / 1024.0 ** 2, grouping=True) + ' MB')
df_test['size_gb'] = df_test['size'].astype(int).apply(lambda x: locale.format("%.1f", x / 1024.0 ** 3, grouping=True) + ' GB')
df_test
dir size size_kb size_mb size_gb
0 /Users/uname1 994933 971.6 KB 0.9 MB 0.0 GB
1 /Users/uname2 109338711 106,776.1 KB 104.3 MB 0.1 GB
[2 rows x 5 columns]
我已经运行了超过120,000行,根据%timeit,每列大约需要2.97秒* 3 = ~9秒。
有什么办法能让它快点吗?例如,我可以从apply中一次返回一列并运行3次,我可以一次返回所有三列以插入到原始的数据框架中吗?
我发现的其他问题都希望接受多个值并返回一个值。我想取一个值并返回多个列。
您可以从包含新数据的应用函数返回一个Series,从而避免需要迭代三次。将axis=1传递给apply函数,将函数的大小应用到数据框架的每一行,返回一个要添加到新数据框架的序列。这个序列s包含新的值,以及原始数据。
def sizes(s):
s['size_kb'] = locale.format("%.1f", s['size'] / 1024.0, grouping=True) + ' KB'
s['size_mb'] = locale.format("%.1f", s['size'] / 1024.0 ** 2, grouping=True) + ' MB'
s['size_gb'] = locale.format("%.1f", s['size'] / 1024.0 ** 3, grouping=True) + ' GB'
return s
df_test = df_test.append(rows_list)
df_test = df_test.apply(sizes, axis=1)
我想在groupby上使用apply。我试着用你建议的方法。它确实对我有帮助,但不是全部。
添加result_type='expand'没有工作(因为我在系列上使用apply而不是DataFrame?)和zip(*___),我失去了索引。
如果其他人也有同样的问题,下面是我(最终)解决它的方法:
dfg = df.groupby(by=['Column1','Column2']).Column3.apply(myfunc)
dfres = pd.DataFrame()
dfres['a'], dfres['b'], dfres['c'] = (dfg.apply(lambda x: x[0]), dfg.apply(lambda x: x[1]), dfg.apply(lambda x: x[2]))
或者你知道更好的办法。告诉我。
如果这超出了我们讨论的范围,请告诉我。
非常酷的答案!谢谢Jesse和jaumebonet!以下是我对以下方面的一些观察:
邮政编码(*……
... result_type = "扩大")
虽然expand更优雅(pandifyed),但**zip至少快2倍。在下面这个简单的例子中,我的速度快了4倍。
import pandas as pd
dat = [ [i, 10*i] for i in range(1000)]
df = pd.DataFrame(dat, columns = ["a","b"])
def add_and_sub(row):
add = row["a"] + row["b"]
sub = row["a"] - row["b"]
return add, sub
df[["add", "sub"]] = df.apply(add_and_sub, axis=1, result_type="expand")
# versus
df["add"], df["sub"] = zip(*df.apply(add_and_sub, axis=1))